Еще несколько примеров того, почему кодирование на Kotlin удобнее, чем на Java. 🖖

В предыдущем посте я упомянул несколько причин, по которым я предпочитаю кодирование на Kotlin, а не на Java. Если вы его пропустили, можете прочитать здесь:



В этом мы продолжаем с того места, на котором остановились. Вот еще семь причин, по которым Kotlin должен быть вашим предпочтительным языком, а не Java:

1. Изменяемые (var) и неизменяемые типы (val) в Котлине

В Kotlin переменные обычно предпочтительно объявлять как val и заимствовать эти конструкции из других языков.

Рассмотрим этот пример:

У нас есть Robot класс с тремя свойствами, которые по умолчанию val. Затем мы создаем новый объект Robot и распечатываем его свойства.

Строка 6 выдает предупреждение компилятора:

Предупреждение: (6, 5) Переменная никогда не изменяется и может быть объявлена ​​неизменной с помощью ‘val’

Сладкий! Язык, явно поощряющий неизменность. 😍

Мы можем обновить "chappie" val, чтобы исправить это. (Прочтите подробное объяснение val и var в этой статье ProAndroidDev).

Приведенный выше код по-прежнему выглядит немного повторяющимся, и его можно улучшить:

Обратите внимание на строки 8–12: мы, по сути, извлекаем свойства chappie робота каждый раз, а затем распечатываем их. Это можно было бы заменить предложением with для импорта вещей в область видимости.

2. Карты

Итак, какова наиболее распространенная структура данных, которую мы все используем, как программисты? List или Map верно?

Самый простой способ создания карты, похожей на Java, показан ниже. Здесь мы используем хэш-карту для создания сопоставления строк со значением ключа. Довольно стандартный материал.

// Old Java way
    val map = HashMap<String, String>()
    map.put("Stack", "Jeff")
    map.put("Overflow", "Joel")

Однако в Kotlin мы можем сделать это немного более читаемым способом. Люди, пришедшие из Python, распознают использование индексов для присвоения значения ключа в существующей карте, как показано ниже:

// We can replace .put with indices to make it a little more nicer
    map["Another"] = "Jared"
    map["Hello"] = "World"

Мы также можем представить карту как конструктор с парами значений ключа, как показано ниже:

// Or even create a map with use of builders such as below
    val anotherMap = mapOf(
            Pair("Stack", "Jeff"),
            Pair("Overflow", "Joel")
    )

Однако даже этого недостаточно. Kotlin дает гораздо более читаемый способ представления вышеуказанной конструкции с помощью инфиксной функции to. В основном это означает, что именно вы думаете об этом в своей голове.

val finalMap = mapOf(
            "Stack" to "Jeff",
            "Overflow" to "Joel")

Теперь вы знаете очень простой и лаконичный способ создания карты. Однако чаще всего вам может понадобиться продолжить итерацию для достижения некоторой функциональности.

Вот традиционный способ сделать это:

// Iterate over map the old way
    for (entry in map.entries) {
        println("${entry.key} -> ${entry.value}")
    }

Хотя это работает, есть немного лучший и краткий способ представить приведенную выше общую логику. Мы можем напрямую распаковать результат .entries в пару и затем использовать его. Намного проще!

// Unpacking the result values and using it directly
    for ((key, value) in map.entries) {
        println("$key -> $value")
    }

3. Удаление назначений из блоков "if-else’" или "когда"

Большинство из нас написали бы некоторую версию этого кода: на основе заданного кода состояния в ответе API мы что-то делаем с результатом. Либо пройти / не пройти утверждение, либо в этом случае просто сообщить результат.

Приведенный выше код может быть идиоматически написан на Kotlin путем снятия присваивания с if.. Последний оператор в условном (if или else) возвращается «автоматически» без необходимости упоминания оператора return. Также обратите внимание, что тип anotherResult также является предполагаемым типом.

Как и if-else, у нас есть мощное предложение when в виде мощного оператора switch case.

Предположим, у вас есть простая функция, которая, в зависимости от различных кодов состояния, возвращает то, что они на самом деле означают.

Теперь, когда этот код работает, он довольно шумный для глаз, поэтому очевидно, что он может быть лучше представлен в Kotlin. Мы можем вывести return из when, чтобы не вводить это все время для каждого случая, а также сгруппировать связанные условия вместе, как показано ниже:

fun apiResponsesIdiomatic(response : Response) : String {
    return when(response.statusCode) {
        in setOf(200, 201, 204) -> "Success"
        300 -> "Redirection"
        400 -> "Bad request"
        401 -> "Unauthorized"
        500 -> "Server error"
        else -> "Unknown"
    }
}

Кроме того, мы могли бы даже назначить это выражение функции, как мы делали это ранее с операторами if-else:

4. Аннулирование

Kotlin стремится исключить исключение нулевого указателя, которое также называют ошибкой в ​​миллиард долларов, путем введения набора явных конструкций, чтобы пометить какой-либо тип как имеющий значение Nullable. Кроме того, по умолчанию все типы в Kotlin не допускают значения NULL.

Рассмотрим приведенный выше код:

Вы заметили ? после String в аргументе readMeByChar функции (строка 5)? Это означает, что text может иметь значение NULL, и любая попытка выполнить действие, такое как получение длины строки, приведет к предупреждению компилятора. Поскольку текст может быть нулевым, нам нужно явно обрабатывать нулевой регистр, и именно здесь Kotlin действительно сияет.

Kotlin заставляет вас рассматривать возможность использования NULL как первоклассную проблему и всегда писать код с учетом этого.

В приведенном выше коде text отмечен как допускающий значение NULL. Что, если мы хотим предпринять какое-то действие в зависимости от того, имеет ли текст значение или передается как null? В Котлине есть специальный оператор под названием Оператор Элвиса ?:.

Мы можем написать заявление, подобное приведенному ниже, которое переводится как:

Если текст не равен нулю, верните его значение. Если это не так, присвойте константам значение по умолчанию. Это краткий способ представления этой логики, избавляющий нас от необходимости писать if-else оператор.

val s = text ?: " "

Это большая тема, которая может вызвать некоторый дискомфорт от понимания. Пожалуйста, прочтите официальную документацию, чтобы понять это еще больше.

5. Функциональный стиль

Kotlin - это мультипарадигмальный язык, поддерживающий действительно хороший функциональный стиль написания кода.

Давайте посмотрим на пример ниже:

У нас есть простая функция, которая принимает числа от 1 до 100 и, если число делится на 16, печатает шестнадцатеричное значение этого же числа.

По сути, for с условием if выглядит как карта фильтров, верно? Таким образом, мы можем легко переписать это, как показано ниже, с filter и map, принимающими лямбда-функцию.

val list = nums
            .filter { it -> it % 16 == 0 }
            .map { it -> "0x" + it.toString(16) }

Также it -> здесь необязателен и может быть удален.

val list = nums
            .filter { it % 16 == 0 }
            .map { "0x" + it.toString(16) }

Сравнивая это с более ранней конструкцией с блоками for и if-else, это гораздо более выразительно и ясно передает намерение.

6. Необработанные струны

В Kotlin мы можем заключать длинные строки в """ и обрабатывать их как необработанную строку (точно так же, как Python), что позволяет нам легко писать разумную строку вместо того, чтобы иметь армию из + and "\n" для представления даже самых простых структур JSON.

// Awesome
    val rawString = """
       Tell me and I forget.
       Teach me and I remember.
       Involve me and I learn
    """.trimIndent()
// Nightmare in Java to even write a simple JSON in a .java file
String hello = "{\n" +
                "  \"Foo\": {\n" +
                "    \"Bar\": \"Woah\"\n" +
                "  }\n" +
                "}"

7. Импорт

При работе в любой профессиональной среде может случиться так, что есть несколько классов с одинаковым именем, которые вы, возможно, захотите использовать в одном классе. В Java 8 мы должны обращаться к полностью определенному пути для одного из классов.

Ну не более того.

В Kotlin вы можете просто присвоить классу псевдоним с ключевым словомas. Это делает потребляющий код более читабельным.

import foo.Bar // Bar is accessible
import bar.Bar as bBar // bBar stands for 'bar.Bar'

Хорошие вещи ✌️

Как вы можете видеть после прочтения этой серии, Kotlin приносит глоток свежего воздуха в качестве мультипарадигмального языка во вселенную JVM. Эти концепции - лишь верхушка айсберга, и если вы все еще не уверены в использовании Kotlin, что ж, сделайте рывок веры. Тебе это понравится.

Это завершение этой серии! Надеюсь, вам понравилось это читать, и не стесняйтесь оставлять свои отзывы в комментариях. До скорого. Удачного кодирования. Ваше здоровье! 🙌