Kotlin
A concise multiplatform language developed by JetBrains
Публикации и ответы на комментарии в блогах JetBrains не выходят на русском языке с 2022 года.
Приносим извинения за неудобства.
Вышел Kotlin 1.6.0
Мы выпустили новую версию Kotlin 1.6.0, где были стабилизированы исчерпывающие выражения when
, а также добавлен плагин Kover и новый менеджер памяти Kotlin/Native. Другие возможности языка и стандартной библиотеки, появившиеся в версии 1.5.30, также стабилизированы. Мы благодарны всем, кто прислал свои отзывы, комментарии и предложения. Если вы еще не попробовали новые функции, сделайте это сейчас!
В этой статье мы расскажем о следующих обновлениях:
- функции языка: sealed-выражения when (when statement), останавливаемые функции и преобразования suspend, создание объектов классов аннотаций, улучшенный вывод обычных типов и вывод типов построителей;
- Kotlin/JVM: оптимизация делегированных свойств и повторяемые аннотации;
- Kotlin/Native: превью новой модели управления памятью, поддержка Xcode 13, кросс-компиляция проектов с целевой платформой Windows, обновления LLVM и компоновщика, улучшения производительности и унифицированный ABI плагинов компилятора;
- возможность отключения скачивания Node.js и Yarn для Kotlin/JS;
- анонс Kover;
- стандартная библиотека: новые функции стандартного ввода, стабилизация
typeOf()
и API Duration, а также других функций stdlib.
Подпишитесь на наш блог, чтобы не пропустить информацию об обновлениях Kotlin
Как обновиться
Если вы пользуетесь IntelliJ IDEA или Android Studio, то сможете автоматически обновиться до новой версии Kotlin, как только она будет доступна в них.
Подробнее об установке Kotlin 1.6.0.
Возможности языка
Опираясь на ваши отзывы, мы стабилизировали функции, появившиеся в Kotlin 1.5.30.
Sealed (исчерпывающие) выражения when
Пользователи давно ждали появления sealed-выражений (statement) when
, когда компилятор Kotlin предупреждает, если выражение when не является исчерпывающим. В результате код становится безопаснее, и вам не нужно вводить собственные функции.
Kotlin всегда выполнял исчерпывающие проверки выражений (expression) when
для sealed-классов, перечислений и логических типов. Это удобно при использовании алгебраических типов данных для моделирования предметной области. Например, у вас могут быть различные предпочтительные контактные данные для пользователей приложения, смоделированные как иерархия sealed-классов:
Теперь представьте себе, что вы написали выражение, которое возвращает другой результат в зависимости от контактной информации. Если вы забыли обработать все типы, имеющиеся в приложении, компилятор сообщит об ошибке:
Это очень полезно и при написании кода, и при его последующей поддержке. Если в дальнейшем вы добавите еще один тип предпочитаемой контактной информации, то компилятор обязательно проверит, не забыли ли вы обработать типы по всему коду.
Однако до выхода Kotlin 1.6 код, использующий выражения when
, успешно компилировался, хотя он не обрабатывал отправку уведомлений пользователям посредством мгновенных сообщений:
Выполнялась только слабая инспекция в IDE, сообщения от компилятора отсутствовали. Начиная с версии Kotlin 1.6, компилятор выдает следующее предупреждение:
Non-exhaustive 'when' statements on sealed class/interface will be prohibited in 1.7. Add an 'is InstantMessage' branch or 'else' branch instead.
В Kotlin 1.7 это станет ошибкой, поэтому случайно забыть об этом уже не получится. Подробнее об этом изменении и его последствиях можно узнать в тикете KT-47709.
Останавливаемые функции как супертипы
В Kotlin 1.6 стабилизирована поддержка использования функциональных типов suspend
как суперинтерфейсов. Это был один из недостающих элементов поддержки корутин Kotlin.
При создании API Kotlin обычно используют функциональные типы, если нужно настроить поведение различных функций библиотек. Например, в интерфейсе Job в API kotlinx.coroutines
есть функция-член класса, которая выглядит примерно так:
Ее удобно использовать с такими лямбдами, как invokeOnCompletion { doSomething() }
. Если у вас есть класс, который вы хотите использовать для обработки завершения выполнения, можно упростить и оптимизировать код, реализовав функциональный тип () -> Unit
прямо в классе, не создавая дополнительную лямбду:
Начиная с Kotlin 1.6, такая оптимизация возможна и с останавливаемыми функциями. Допустим, ваши API принимают останавливаемые функциональные типы, например:
В этом случае у вас больше нет ограничений на использование лямбд и останавливаемых функций в коде. Соответствующие останавливаемые функциональные типы можно также реализовать в классе:
Преобразование в останавливаемые типы
В Kotlin 1.6 стабилизированы преобразования из обычных в останавливаемые функциональные типы. Теперь вы можете применять подходящие обычные функциональные типы там, где ожидается параметр останавливаемого типа. Компилятор выполняет преобразование автоматически.
Это позволило устранить небольшую, но раздражающую непоследовательность во взаимодействии обычных и останавливаемых функций в Kotlin. Если у вас есть функция высшего порядка, принимающая останавливаемую функцию, например вызов оператора collect в Kotlin Flow, для его вызова необязательно использовать лямбду, как здесь:
Вместо этого можно вставить в вызов collect
ссылку на функцию processItem
и получить тот же результат:
После этого можно извлечь ссылку на функцию обработки в переменную, чтобы соответствующим образом изменить ее поведение в коде. Однако в предыдущих версиях Kotlin это не работало. Дело в том, что в этом случае мы имеем обычную функцию, передаваемую как параметр останавливаемого типа:
В Kotlin 1.6 приведенный выше код успешно компилируется и работает.
Улучшенный вывод для рекурсивных универсальных типов
Начиная с версии 1.6.0, компилятор Kotlin может вывести аргумент типа, опираясь только на верхние границы диапазона соответствующего параметра типа, являющегося по умолчанию рекурсивным универсальным типом. Благодаря этому можно создавать разнообразные шаблоны с рекурсивными универсальными типами, которые часто используются в Java для API билдеров.
Улучшения вывода типов построителя
В Kotlin 1.5.30 появился параметр компилятора -Xunrestricted-builder-inference
, с помощью которого можно было получать информацию о вызове построителя изнутри лямбд построителя. В частности, это позволило совершать вызовы, возвращающие экземпляр еще не выведенного типа, такого как get()
внутри лямбды buildList()
.
Начиная с версии 1.6.0 больше не нужно указывать -Xunrestricted-builder-inference
, чтобы совершать запрещенные прежде вызовы. Параметр компилятора -Xenable-builder-inference
позволяет также писать собственные универсальные построители, не применяя аннотацию @BuilderInference
и автоматически включать вывод типов построителя, если вывод обычных типов не позволяет вычислить информацию типа.
Более длительная поддержка прежних версий API
Начиная с версии 1.6.0, можно вести разработку с использованием не двух, а трех прежних версий API (помимо текущей стабильной версии). В настоящий момент это API версий 1.3, 1.4, 1.5 и 1.6.
Kotlin/JVM
Повторяемые аннотации с временем хранения RUNTIME. В Kotlin, как и в Java 8, есть повторяемые аннотации. В Kotlin 1.6 эта функциональность стала совместима с Java, а @kotlin.annotation.Repeatable
теперь принимает любое значение времени хранения и делает аннотацию повторяемой и в Kotlin, и в Java. Кроме того, теперь повторяемые аннотации Java поддерживаются и в Kotlin.
Kotlin/Native
Мы выпустили экспериментальную версию нового менеджера памяти Kotlin/Native. С появлением этой функциональности мы сделали еще один шаг к единообразию разработки в мультиплатформенных проектах. Новый менеджер памяти устраняет существующие ограничения на совместное использование объектов в разных потоках и предлагает параллельные программные примитивы, которые полностью защищены от утечек памяти, безопасны и не требуют специального управления или аннотаций со стороны разработчиков.
Вы можете спокойно обновить Xcode и продолжать работу над проектами Kotlin, поскольку новая версия Kotlin/Native поддерживает Xcode 13.
Компиляция проектов Windows на любом хосте. Проекты Windows mingwX64
и mingwX86
можно компилировать на любом хосте, поддерживающем Kotlin/Native.
Мы переработали зависимость LLVM, используемую внутри Kotlin/Native. Это дало ряд преимуществ, позволило обновить версию LLVM до 11.1.0 и уменьшить размер зависимости.
Унификация ABI плагинов компилятора с бэкендами JVM и JS IR. Теперь плагин Kotlin Multiplatform Gradle может использовать для Kotlin/Native тот же встраиваемый jar-файл компилятора, что и для бэкендов JVM и JS IR. Благодаря этому для Native и других поддерживаемых платформ можно использовать одни и те же артефакты плагинов компилятора.
Kotlin/JS
При сборке проекта на сервере без подключения к интернету теперь можно отключить скачивание Node.js и Yarn для проектов Kotlin/JS и использовать уже установленные на хосте экземпляры.
Kover
Проблема точного определения покрытия кода существует еще с самого первого релиза. Код Kotlin поддерживают несколько отличных инструментов, например JaCoCo, но они не интегрированы полностью в наш тулчейн и мультиплатформенные проекты. В новой версии Kotlin мы подошли к решению этой проблемы. Представляем Kover — новый плагин Gradle, который оценивает покрытие кода Kotlin, собранного компилятором Kotlin/JVM. Он пока находится на ранней стадии разработки и имеет статус экспериментальной функциональности. Мы будем благодарны вам за отзывы об этом инструменте, оставленные в GitHub.
Подробнее о Kover можно узнать, посмотрев это видео.
Стандартная библиотека
В Kotlin 1.6.0 мы выполнили три пункта официального плана развития стандартной библиотеки: избавились от !!
после readLine()
, стабилизировали typeOf()
и обеспечили стабильный API Duration. Кроме того, были стабилизированы следующие функции stdlib:
- построители коллекций;
- побитовые операции отражения с целыми числами;
- функция Regex для разделения строкового значения и создания последовательности.
Кроме того, мы добавили возможность вызова compareTo
в инфиксной нотации и обеспечили одинаковое поведение функций replace()
в JVM и JS.
Новые функции для стандартного ввода
В Kotlin 1.6.0 больше не нужно использовать оператор проверки ненулевого значения !!
после считывания строки стандартного ввода. Это упрощает изучение Kotlin и делает работу удобнее для новичков.
Мы добавили новые функции для чтения с консоли, которые работают следующим образом:
readln()
выдает исключение при достижении конца файла. Эту функцию следует использовать вместо проверки результатаreadLine()
на значениеnull
с помощью оператора!!
.- Новая функция
readlnOrNull()
— альтернативный вариант, возвращающий значениеnull
. Она работает так же, как прежняя функцияreadLine()
, но у нее более очевидное имя.
В настоящий момент эти функции доступны для JVM и Native. Правила именования этих функций соответствуют их аналогу println()
, что особенно важно для новичков.
Стабильный API Duration
Благодаря вашим отзывам нам удалось стабилизировать API Duration и выполнить соответствующий пункт плана развития.
Помимо более понятных правил выполнения Duration.toString()
и новых функций вычленения объектов Duration из строк, которые появились в режиме предпросмотра в версии 1.5.30, в API Duration были сделаны следующие изменения:
- В компонент
days
функцииtoComponents
был добавлен типLong
вместоInt
, чтобы значения не обрезались. - Перечисление
DurationUnit
больше не является псевдонимом типа. В JVM отсутствуют случаи его использования в качестве псевдонима для java.util.concurrent.TimeUnit
. - В соответствии с пожеланиями сообщества мы вернули свойства расширения, такие как
Int.seconds
. Для ограничения возможностей их использования они доступны только в компаньоне класса Duration.
Стабильная функция typeOf()
В Kotlin 1.6.0 стабилизирована функция typeOf()
. Тем самым мы выполнили соответствующий пункт плана развития. Начиная с версии 1.3.40, typeOf()
была доступна на платформе JVM в качестве экспериментального API. Теперь ее можно использовать на любой платформе Kotlin и получить представление KType
для любого типа Kotlin, выводимого компилятором.
Стабильные построители коллекций
В Kotlin 1.6.0 стабилизированы функции построителей коллекций: buildMap()
, buildList()
и buildSet()
. Возвращаемые построителями коллекции теперь сериализуются в состоянии только для чтения.
Стабильные побитовые операции отражения с целыми числами
В Kotlin 1.6.0 стабилизированы функции rotateLeft()
и rotateRight()
, которые отражают двоичное представление числа влево или вправо на указанное число битов.
Стабильная функция Regex для разделения строкового значения и создания последовательности
Наконец, в 1.6.0 стабилизирована функция splitToSequence()
для регулярных выражений, разделяющих строковое значение для создания последовательности.
compareTo в инфиксной нотации
Мы добавили возможность вызова функции Comparable.compareTo
в инфиксной нотации для сравнения порядка двух объектов:
Последовательное поведение replace() и replaceFirst() в JVM и JS
До выхода Kotlin 1.6.0, функции replace()
и replaceFirst()
для регулярных выражений по-разному вели себя в JVM и JS, если заменяющая строка содержала ссылку на группу. Теперь их поведение в Kotlin/JS совпадает с поведением в JVM.
Совместимость
Как и при выходе всех релизов, включающих новые функции, с выходом Kotlin 1.6.0 завершаются ранее анонсированные циклы прекращения поддержки некоторых возможностей. Все эти ситуации были тщательно рассмотрены языковым комитетом и перечислены в нашем руководстве по совместимости Kotlin 1.6. Информацию об этих изменениях можно также найти в YouTrack.
Как установить Kotlin 1.6.0
Если вы уже пользуетесь IntelliJ IDEA или Android Studio, IDE автоматически предложит вам обновиться до версии 1.6.0. Также можно обновить версию вручную — следуйте этой инструкции.
Для полной поддержки Kotlin вы всегда можете скачать свежие версии этих IDE:
- IntelliJ IDEA — разработка приложений на Kotlin для разных платформ;
- Android Studio — разработка приложений под Android и кросс-платформенных мобильных приложений.
Также проверьте, что вы обновили библиотеки kotlinx до совместимых версий и указали версию Kotlin 1.6.0 в билд-скриптах ваших проектов.
Скачать компилятор для командной строки можно с GitHub-страницы релиза.
Что делать, если вы столкнулись с проблемами?
- Обратитесь за помощью в канале в Slack (воспользуйтесь этим приглашением).
- Сообщите о проблеме в нашем баг-трекере YouTrack.
Следите за новостями о новых возможностях Kotlin! Чтобы подписаться на рассылку об обновлениях языка, заполните форму справа от статьи.
Что еще можно почитать и посмотреть
- План развития Kotlin
- Kover — плагин для анализа покрытия кода
- Что нового в Kotlin 1.6.0 — документация
- Что нового в Kotlin 1.6.0 — на YouTube
- Руководство по совместимости Kotlin 1.6
- Мы выпустили Kotlin 1.5.30!
Кто прислал больше всего сообщений о пробемах
Ryan Nett (48 тикетов), Zac Sweers (22 тикета), Tianyu Geng (18 тикетов), zhelenskiy (18 тикетов), Thodoris Sotiropoulos (15 тикетов), AndroidDeveloperLB (14 тикетов), Morgan, Bartholomew (14 тикетов), Mikhail Naftal (14 тикетов), Louis CAD (12 тикетов), Philip Wedemann (12 тикетов), Victor Turansky (11 тикетов), Igor Wojda (11 тикетов), Martin Bonnin (11 тикетов), Iaroslav Postovalov (11 тикетов), Cedric (10 тикетов), 凛 (9 тикетов), Ben Woodworth (8 тикетов), Tianyi Guan (8 тикетов), Chris Povirk (8 тикетов), Alon Albert (8 тикетов).
Внешние контрибьюторы
Мы хотим поблагодарить всех контрибьюторов, чьи пул-реквесты включены в этот релиз: Pyos, Tianyu Geng, Jinseong Jeon, Steven Schäfer, Mark Punzalan, Hung Nguyen, Mads Ager, Ting-Yuan Huang, Matthew Gharrity, Ivan Gavrilovic, Xin Wang, ov7a, Jiaxiang Chen, Yigit Boyar, Bingran, bracadabra, Steffi Stumpos, Andrey Kuleshov.
Ваша команда Kotlin
The Drive to Develop
Автор оригинальной статьи: