Вышел Kotlin M3

в 3:28, , рубрики: java, kotlin, Блог компании JetBrains, Программирование, метки:

Наш язык программирования неуклонно развивается: мы выпустили Kotlin M3 — большой milestone, в который вошло много интересного: от обновления домашней страницы до поддержки режима скриптов. А еще наша команда начала активный «догфудинг»: в ближайшее время все больше кода в проекте Kotlin будет писаться на Kotlin.

В этом посте я кратко опишу две наиболее интересные вещи, которые были сделаны в M3: мульти-декларации и «расщепление» интерфейсов коллекций.

Мульти-декларации

Как это выглядит. Теперь в Kotlin можно писать, например, такой код:

val map = hashMap("one" to 1, "two" to 2, "three" to 3)
for ((k, v) in map) {
    println("$k -> $v")
}

Обратите внимание на то, что в for объявлена не одна переменная, а две, в круглых скобках. Это один из примеров множественных деклараций, или «мульти-деклараций» (multi-declarations). Более простой пример:

val (a, b) = pair

В результате такого объявления появляются две переменные, которые можно использовать абсолютно независимо друг от друга.

Как это работает. Декларация из последнего примера транслируется в такой код:

val a = pair.component1()
val b = pait.component2()

Как и многое другое в Kotlin, мульти-декларации опираются на конвенцию: функции componentN() вызываются по имени, то есть могут быть объявлены как в классе pair, так и вне его — в качестве extensions. Это дает возможность обходить map так, как было показано в начале: для Map.Entry объявлены две extension-функции:

fun <K, V> Map.Entry<K, V>.component1() = getKey()
fun <K, V> Map.Entry<K, V>.component2() = getValue()

В общем случае для каждого класса нужно реализовывать такие функции по-своему, но есть один очень распространенный случай: когда класс просто хранит данные и больше ничего не делает. Это называется «класс данных» (data class):

data class User(val name: String, val password: String) {}

Аннотация «data» сообщает компилятору, что нужно сгенерировать в этом классе несколько стандартных методов: equals()/hashCode(), toString() и component1(), component2(). Все эти функци используют свойства класса, объявленные в первичном конструкторе, например, component1() возвращает name, а component2() — password:

val (name, pass) = getUser()

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

Еще про мульти-декларации в этом посте по-английски.

Типы коллекций

Коллекции используются везде и всегда, поэтому от дизайна соответствующей части библиотеки во многом зависит удобство языка программирования. Именно поэтому многие «альтернативные» языки на платформе Java используют собственные коллекции, несовместимые со стандартными, что создает различные трудности при использовании Java-библиотек (которых большинство и благодаря которым Java — такая замечательная платформа).

Kotlin делает упор на совместимость с существующим кодом, поэтому мы используем стандартные классы коллекций, но делаем их лучше:
image

Обратите внимание, что интерфейсы коллекций делятся на read-only и mutable. Старые добрые java.util.ArrayList и HashSet по-прежнему доступны — это изменяемые коллекции. Но если где-то написано просто List<String>, изменять его нельзя.

Это помогает не только навести порядок, но и упростить себе жизнь: теперь можно присваивать List<String> туда, где ожидался List<Any>, потому что неизменяемые коллекции ковариантны.

Заключение

В M3 вошло еще много чего интересного. Подробнее об этом можно почитать здесь (по-английски).

Инструкция по установке — здесь (нужна IntelliJ IDEA 12).

Как всегда, мы будем благодарны за Ваши замечания/соображения/пожелания. Приятного Kotlin'а :)

Автор: abreslav

Поделиться

* - обязательные к заполнению поля