10 главных конструкций языка Kotlin
Почти как Java, но есть отличия.
Чтобы быстро начать программировать на языке, достаточно знать несколько основных конструкций и общих правил написания кода. Со временем вы освоите все нюансы, а на старте можно использовать что-то попроще.
Если вы не знаете, зачем нужен Kotlin и что на нём программируют, почитайте нашу статью про Kotlin. А если знаете — вот вам краткий справочник по основам языка.
👉 В Kotlin будет много конструкций, похожих на Java. Это нормально, потому что Kotlin работает тоже поверх виртуальной машины JVM, как и Java.
Точка с запятой в Котлине не нужна.
Комментарии
Всё как обычно — есть однострочные и многострочные комментарии:
// Это однострочный комментарий
// Для каждой строки нужно добавлять его отдельно
/* А это — многострочный
его можно сделать любой длины,
если в начале и в конце поставить нужные символы */
Многие программисты ругают Kotlin за то, что ключевые слова для переменной и константы отличаются всего на одну букву:
val — объявляет константу
var — объявляет переменную
Из-за этого легко ошибиться и сделать константу вместо переменной и наоборот.
Ввод и вывод
Чтобы ввести что-то с клавиатуры, нам нужна переменная, где будет храниться результат ввода и команда readLine(). Эта команда ждёт, когда пользователь введёт любые данные и нажмёт Enter. После этого всё, что ввёл пользователь, отправляется в ту переменную.
Для вывода используются команды print() и println() — первая оставляет курсор на той же строке, а вторая после вывода переводит курсор на новую строку.
Чтобы вывести значение переменной в команде вывода, перед переменной ставят знак доллара:
Присваивание и сравнение
Всё так же, как в Java, но без точек с запятой:
// это присваивание
x = 10
// а это — сравнение x и 10
// результат сравнения отправляется в переменную b
var bol: Boolean
b = (x == 10)
Условный оператор if
Работает как обычно: сначала проверяется условие, и если оно истинно — выполняется код, который идёт после условия. Если результат проверки ложный — выполняется код, написанный после else, или не выполняется ничего, если такого блока в условии нет. Условие пишется в скобках, фигурные скобки можно не писать, если нужно выполнить только одну команду.
Оператор множественного выбора when
Аналог классического Case или Switch из других языков программирования. Команда смотрит на значение переменной, которое к ней поступило, и сравнивает это значение со своим списком вариантов. Если есть совпадение — выполняется нужная команда.
Циклы
Проще всего работать с циклом for: достаточно указать имя переменной цикла и диапазон, в котором она будет меняться:
При желании можно указать шаг цикла внутри диапазона (по умолчанию он равен единице):
for (i in 1..6 step 2) <
print(«$i «) // на экране появятся числа 1, 3 и 5
>
Циклы с предусловием и с постусловием выглядят и работают как в обычном Java:
Функции
У функций в Kotlin полная свобода:
👉 А ещё в Kotlin, как и в Java, каждая программа состоит из функций и каждая команда должна быть внутри какой-то функции. Основная функция программы называется main.
Самое простое объявление и использование функций в Kotlin выглядит так:
Классы
Классы в Котлине поддерживают полноценные конструкторы и инициализации, но для старта достаточно объявить имя класса и его содержимое:
Объекты
Как и в большинстве ООП-языков, для создания нового объекта достаточно указать класс, от которого произойдёт объект. После этого с объектом можно работать по всем правилам объектно ориентированного программирования:
Проблема nullable-типов в том, что многие методы их узких классов-аналогов (без поддержки null) становятся недоступными.
На скрине показано, что несмотря на то, что переменная b не содержит null, использовать свойства и методы обычной строки нельзя.
Как быть в таких ситуациях? Очевидный ответ – проверить значение переменной на null. Если оно не является null, то с помощью оператора as привести его к узкому типу и только после этого вызывать методы.
Однако умный компилятор Kotlin позволяет не делать такое приведение вручную. Если сравнение в заголовке if возвращает истину (переменная не равна null), то в области действия сравнения компилятор будет считать это значение обычным. Как бы сам временно приведет переменную к ненуллабл-типу. Поэтому код выше упрощается до такого:
Если требуется сохранить в переменную длину строки, а также какой-либо числовой сигнал, если был null, потребуется ветка else:
Таким образом проблема nullable-типов в Kotlin решается просто. Однако несколько громоздко и, даже если записать if-else в одну строку, длинно. Поэтому в языке предусмотрены специальные операторы и функции для работы с nullable-типами. В этом уроке будут рассмотрены три оператора Kotlin – оператор безопасного вызова, оператор «элвис» и утверждение «это не null».
?. – оператор безопасного вызова
Оператор безопасного вызова, обозначаемый вопросительным знаком с точкой, похож на проверку на null с if в варианте без else. Он проверят, что значение слева от него не равно null. Если же оно равно null, то ничего не происходит. Точнее, все выражение возвращает null.
Поскольку выражение с оператором безопасного вызова метода потенциально может вернуть null, то значение всего выражения с этим оператором всегда будет принадлежать какому-либо nullable-типу.
?: – оператор «элвис»
Оператор, обозначаемый вопросительным знаком с двоеточием, подобен проверке на null в варианте if-else. Он возвращает значение слева от себя, если оно не null. И возвращает значение справа от себя, если то, что слева, – null.
Переменная c будет содержать либо строку, которую вернула функция readLine(), либо пустую строку, если readLine() вернет null. Избавимся от переменной c :
!! – утверждение «это не null»
Поэтому, несмотря на удобство этого оператора, его следует использовать только там, где вы уверенны, что null быть не может.
Немного о Kotlin
На днях JetBrains после пятилетней работы выпустила первый релиз языка Kotlin. Давайте посмотрим, что же это за язык, попробуем разобраться зачем и для кого он, какие имеет функциональные особенности. Скорее всего в статью затесались и личные впечатления от языка, но я старался, чтобы они не влияли на изложение полезной информации. Если вы еще ничего или почти ничего не знаете о Kotlin, то я завидую вам, ибо по моему ощущению почитать про инструмент, который ты долго ждал, сродни распаковке новогоднего подарка. Впрочем судите сами.
Что такое Котлин
Котлин — это небольшой остров в Финском заливе недалеко от Санкт-Петербурга. Видимо, тем самым создатели дают отсылку к тому, что новый язык, как остров Котлин — младший русский брат далекого острова Ява.
Для кого этот язык
Действительно, новый язык компилируется в JVM байт-код (есть еще и компиляция в JavaScript, но так как релиз компилятора именно в JVM, эту тему придется опять отложить). А это значит, что он может заинтересовать всех, кто имеет дело с Java-машиной и в целом с языками со сборщиком мусора (а с выходом релиза компиляции в JavaScript покрытие и возможности будут еще шире).
Простой и совместимый
Две главных особенности котлина, на мой взгляд, это его простота и полная совместимость с Java. Котлин создавался компанией, которая делает очень много продуктов на Java и которая хорошо разбирается в современных инструментах разработки. Запрос на новый язык витает в воздухе давно, но сделать такой язык, который бы позволил взять (огромную) готовую кодовую базу Java, обычных Java-разработчиков, дать им новый инструмент и бесшовно (но более эффективно) продолжать разработку — такого инструмента до появления котлина не существовало. Создатели нового языка, на мой взгляд, очень хорошо почувствовали потребности бизнеса и разработчиков: бизнесу дали возможность увеличить эффективность разработчиков, а разработчикам дать современный инструмент для разработки. И когда я говорю о «современном инструменте», я, конечно, имею ввиду не только компилятор, но и поддержку в IDE, без которой лично моя деятельность разработчика мне видится совсем немыслимой.
В итоге: простота позволяет использовать язык почти любому Java-разработчику, который готов потратить полчаса на то, чтобы посмотреть туториал или спецификацию языка, обратная совместимость же позволяет использовать язык в уже существующем проекте.
Production-ready
Конечно, в первую очередь, запрос на этот язык был у самой JetBrains, отсюда и некоторое понимание, каким он должен быть. Более того, JetBrains же внутри компании его и тестировала: к моменту выхода этого релиза у компании уже есть как минимум один крупный продукт сделанный чисто на котлине (да, я понимаю, что платформа по прежнему написана на Java). Отсюда можно предположить, что заявления о готовности языка к продакшену не голословны. А из своего же опыта использования котлина с 2012 года могу сказать, что из тех проблем, с которыми я сталкивался в дорелизные времена, до релиза ни одна не дожила. Есть еще небольшие проблемы с плагином для IDEA, но сам компилятор работает как часы.
Совместим с Java 1.6
Это очень важный момент, ведь именно эта версия Java используется во всех современных версиях Android, и, не смотря на запланированный переход на OpenJDK, восьмая версия попадет в руки разработчикам под мобильные устройства не так скоро как хотелось бы. Конечно, есть всякие ретролямбды и другие ухищрения, но котлин — это не только лямбды для андроид, но и современный язык, позволяющий сделать разработку под андроид проще и приятней без особых затрат. А увеличение размера apk совсем не значительно по нынешним временам: 823KB (для версии 1.0.0)
Особенности
Полный список возможностей, конечно, лучше искать в документации, я же постараюсь отразить наиболее важные на мой взгляд моменты в общих словах:
Null safety
Почему-то исторически так сложилось, что эта особенность котлина вспоминается первой. И хотя она безусловно важна, на мой взгляд не является важнейшей. Здесь язык позволяет, определяя переменные, поля, константы и тд, указать, может ли в них храниться ссылка на null. Поднимает на новый уровень идею аннотаций вроде @Nullable и NotNull, позволяет умно приводить к не-nullable типу после проверки её на null. Надо отметить, что бывают случаи, когда эта особенность расходится с моим закостенелым разработкой на Java представлением о том как должны быть сделаны некоторые вещи, но после некоторого раздумья хорошее решение всегда находится.
Выведение типов
Да, котлин почти везде где возможно, умеет вывести тип, однако тип всё же придется определить для публичных методов и свойств, что очень разумно (мне подсказывают, что это неправда — с какой-то версии это убрали):
Extension methods
Возможность, которой мне остро не хватает в Java для увеличения гибкости языка и решений. Заключается в возможности определить метод для типа отдельно от его (типа) объявления. Такая функция, конечно, не будет виртуальной и никак не меняет класса, которому мы добавляем метод, однако позволяет добавить как утилитарную функциональность для уже существующего кода, так и разгрузить интерфейс от этих же утилитарных методов.
Лямбды
Конечно, как любой современный язык с претензией на возможности функцинального программирования, у котлина функция — это сущность первого класса, если переводить дословно. Т.е. функции можно не только объявлять прямо в пакете (из джавы они видны всё равно в классах — по имени файла), но и передавать в качестве параметров, возвращать из других функций и тд. И сейчас, конечно, никого этим не удивишь, но например в сравнении с Java, где синтаксически функций как таковых нет (а только функциональные интерфейсы), в котлине полноценный синтаксис для объявления функции:
Extension-лямбды
Наряду с extension-методами, это еще одна моя любимая фича. Позволяет определить лямбду, которая будет еще и extension-методом. Звучит не очень, да. Посмотрим на примере:
Эта возможность особенно интересно смотрится в билдерах, посмотреть на которые я предлагаю вам самостоятельно — на случай, если вам интересно, как получаются вот такие конструкции:
Inline-фукнции
Помечая функцию как inline мы просим компилятор поместить её по месту использования. Чаще всего такими вещами занимается рантайм, но есть кейзы, когда мы точно знаем, что фукнция это просто шорткат для какого-то действия — особенно эффективно это работает с передаваемыми лямбдами:
Конечно, на такие функции накладывается серия ограничений, подробнее см. документацию.
Делегирование
В котлине есть два типа делегирования. Первый, который позволяет делегировать все методы реализуемого интерфейса к какому-то инстансу этого типа:
У этого синтаксиса есть ряд ограничений. Например, инстанс для делегирования должен быть известен до вызова конструктора.
Второй тип делегирования — это delegated properties. Позволяет определить объект с методами get (и set для var), к которым будет осуществляться делегирование доступа при обращении к свойству объекта.
Generics
Создатели котлина несколько улучшили Java-дженерики. Из-за совместимости с джавой не всё получилось как хотелось бы, но им удалось исправить много неприятных моментов, которые не учли их предшественники при работе над Java 5.
Деструктуризация
Чтобы такой код заработал, возвращаемое значение из someFunc() должно быть типа, у которого есть (можно extension) методы component1(), component2():
Data-классы
Сахар компилятора для создания бинов:
Создает бин с полями + автогенерирует equals+hashCode+toString()+componentN из раздела выше, что позволяет писать такой код:
Полезная вещь, но о нюансах см. пункт «О грустном».
Стандартная библиотека
Конечно, нельзя не упомянуть и стандартную библиотеку. Так как котлин нацелен в первую очередь на работу вместе с Java, то и целиком своей стандартной библиотеки у него нет. Большая часть стандартной библиотеки Kotlin нацелена на улучшение и исправление библиотеки старшего брата — Java. Однако, это тема для другой большой статьи.
О грустном
Вы могли подумать, что это идеальный продукт, но нет, есть и неприятные моменты:
Над плагином еще работать и работать, периодически выдает эксепшены, плохо умеет в toString() в дебаге, а так же любит промахиваться по ссылке на исходник, иногда (видимо из за особенностей инлайна) путает где поставлен брэкпоинт и тому подобные проблемы. Это всё конечно со временем наверняка поправят, но сейчас мы имеем именно это.
Data-классы
Некоторая неряшливость
Конечно, неряшливость в первую очередь в головах, но краткость синтаксиса иногда играет злую шутку, и местами код выглядит неважно. Возможно, наличие стайл-гайда несколько эту проблему исправило бы, но пока иногда приходится постараться, чтобы не только хорошо работало, но и красиво выглядело. Особенно на мой субъективный взгляд страшно выглядят get, set для свойств.
Котлин Операторы
Введение в Kotlin Операторы
Пример:
Операторы в Котлине
Ниже приведены различные типы операторов, используемых в Kotlin
1. Арифметические операторы:
Котлинские арифметические операторы:
Пример:
Примечание: оператор + также используется для конкатенации строк при использовании со строками.
Пример:
package com.examples
fun main (args : Array )
(
val fname = “Laxman” val lname = “das”
val full_name = fname + “ “ + lname println (full_name) // Laxman das
)
2. Назначение операторов
Оператор присваивания используется для присвоения значений переменным. Значение после оценки с левой стороны присваивается переменной с правой стороны. Помимо базового оператора присваивания, Kotlin предоставляет широкий спектр операторов присваивания, которые упомянуты ниже:
Котлин Операторы Назначения:
| оператор | пример | Эквивалентно |
| + = | а + = Ь | а = а + Ь |
| знак равно | а- = Ь | а = аб |
| знак равно | а * = Ь | а = а * Ь |
| знак равно | а / б = | а = а / б |
| знак равно | A% = Ь | A = A% B |
Пример:
3. Обычные операторы:
Котлин Унарные Операторы:
| операторы | пример | Эквивалентно |
| + | + а | + (значение) |
| — | -a | — (ценность) |
| ! | ! | Не (инверсия) |
| ++ | ++ | а = а + 1 |
| — | -a | а = а-1 |
Пример:
Операторы увеличения и уменьшения могут использоваться до и после переменной, но оба имеют разные значения. Если перед именем переменной используется оператор увеличения или уменьшения, то значение этой переменной изменяется в первую очередь перед любой другой операцией над переменной. Если после имени переменной используется оператор увеличения или уменьшения, его значение изменяется после другой операции с этой переменной.
В приведенном выше примере значение b сначала увеличивается на 1, а затем присваивается переменной «increment», тогда как значение c сначала присваивается переменной dec, а затем уменьшается на 1.
4. Сравнение операторов:
Операторы сравнения используются для сравнения двух значений. Эти операторы в основном используются с if-else для выполнения определенного потока после сравнения.
Kotlin Операторы сравнения:
5. Операторы равенства и неравенства:
Kotlin предоставляет набор логических операторов, и эти операторы равенства и неравенства возвращают логическое значение в зависимости от результата сравнения. Эти операторы играют важную роль в потоке логики программы, сравнивая значения и перемещаясь в соответствии с этим.
Котлинское равенство и неравенство Операторы:
| операторы | Смысл | выражение |
| знак равно | Не равно | а! = б |
| == | Равно | а == б |
Пример:
fun main (args : Array )
(
var a = 3
var b = 6
println (a==b) //false println (a!=b) // true
)
6. Логические операторы:
Kotlin предоставляет нижеупомянутые 3 логических оператора, которые возвращают логические значения либо true, либо false.
Логические операторы Kotlin:
| операторы | Смысл | выражение |
| && | True, если все значения верны | a && b (имеется в виду a и b) |
| || | Истинно, если любое из значений истинно | || б (имеется в виду а или б) |
| ! | Истинно, если значение ложно! | (то есть не а) |
Пример:
7. В Операторе:
В котлинском языке оператор In используется для проверки наличия или отсутствия данного объекта в коллекции.
Котлин в Операторах:
| операторы | Смысл | выражение |
| в | Подарок в коллекции b | а в б |
| Не в | Нет в коллекции b | а! в б |
Пример:
fun main (args : Array )
(
val array = intArrayOf(10, 20, 30, 40) If (20 in array)
(
println (“yes 20 is present in array”) // yes 20 is present in array
)
else
(
println (“no 20 is not present in array”)
)
)
8. Оператор диапазона:
Kotlin использует оператор диапазона для создания диапазона значений. Этот оператор очень полезен при работе с циклами. Нет необходимости определять каждое значение, если оно является последовательным, лучше использовать ярлык и определять диапазон, определяющий самое низкое и самое высокое значение.
Kotlin Range Операторы:
9. Индексированный оператор доступа:
Операторы индексированного доступа используются для доступа к любому значению по определенному индексу в массиве. В Kotlin массив начинается с индекса 0.
Операторы индексированного доступа Kotlin:
| операторы | Смысл |
| а (я) | Получить значение по индексу ‘i’ в массиве ‘a’ |
| a (i) = b | Установите значение b в индекс ‘i’ массива ‘a’ |
Пример:
10. Операторы:
Как и другие языки программирования, например C, C ++, Java, Kotlin не имеет побитовых операторов. Он имеет различные функции, которые работают для побитовых операций.
Побитовые операторы Котлина:
| функции | Смысл |
| ЗЫ | Подпись сдвиг влево |
| SHR | Подпись вправо |
| ушр | Беззнаковое смещение вправо |
| и | Побитовый и |
| или | Побитовый или |
| исключающее | Побитовый xor |
| фактура | Побитовая инверсия |
Пример:
Рекомендуемые статьи
Основные типы
В Kotlin всё является объектом, в том смысле, что пользователь может вызвать функцию или получить доступ к свойству любой переменной. Некоторые типы являются встроенными, т.к. их реализация оптимизирована, хотя для пользователя они могут выглядеть как обычные классы. В данном разделе описывается большинство этих типов: числа, символы, логические переменные и массивы.
Числа
Kotlin обрабатывает численные типы примерно так же, как и Java, хотя некоторые различия всё же присутствуют. Например, отсутствует неявное расширяющее преобразование для чисел, а литералы в некоторых случаях немного отличаются.
Для представления чисел в Kotlin используются следующие встроенные типы (подобные типам в Java):
| Тип | Количество бит |
|---|---|
| Double | 64 |
| Float | 32 |
| Long | 64 |
| Int | 32 |
| Short | 16 |
| Byte | 8 |
Обратите внимание, что символы (characters) в языке Kotlin не являются числами (в отличие от Java).
Символьные постоянные
В языке Kotlin присутствуют следующие виды символьных постоянных (констант) для целых значений:
ВНИМАНИЕ: Восьмеричные литералы не поддерживаются.
Также Kotlin поддерживает числа с плавающей запятой:
Нижние подчеркивания в числовых литералах (начиная с версии 1.1)
Вы можете использовать нижние подчеркивания, чтобы сделать числовые константы более читаемыми:
Представление
Обычно платформа Java хранит числа в виде примитивных типов JVM; если же нам необходима ссылка, которая может принимать значение null (например, Int? ), то используются обёртки. В приведённом ниже примере показано использование обёрток.
Обратите внимание, что использование обёрток для одного и того же числа не гарантирует равенства ссылок на них:
Однако, равенство по значению сохраняется:
Явные преобразования
Из-за разницы в представлениях меньшие типы не являются подтипами бОльших типов. В противном случае у нас возникли бы сложности:
Таким образом, будет утрачена не только тождественность (равенство по ссылке), но и равенство по значению.
Как следствие, неявное преобразование меньших типов в большие НЕ происходит. Это значит, что мы не можем присвоить значение типа Byte переменной типа Int без явного преобразования:
Мы можем использовать явное преобразование для «расширения» чисел
Каждый численный тип поддерживает следующие преобразования:
Отсутствие неявного преобразования редко бросается в глаза, поскольку тип выводится из контекста, а арифметические действия перегружаются для подходящих преобразований, например:
Арифметические действия
Kotlin поддерживает обычный набор арифметических действий над числами, которые объявлены членами соответствующего класса (тем не менее, компилятор оптимизирует вызовы вплоть до соответствующих инструкций). См. Перегрузка операторов.
Что касается битовых операций, то вместо особых обозначений для них используются именованные функции, которые могут быть вызваны в инфиксной форме, к примеру:
Ниже приведён полный список битовых операций (доступны только для типов Int и Long ):
Символы
Подобно числам, символы оборачиваются при необходимости использования nullable ссылки. При использовании обёрток тождественность (равенство по ссылке) не сохраняется.
Логический тип
При необходимости использования nullable ссылок логические переменные оборачиваются.
Встроенные действия над логическими переменными включают
Массивы
Также для создания массива можно использовать фабричную функцию, которая принимает размер массива и функцию, возвращающую начальное значение каждого элемента по его индексу:
Строки
Строковые литералы
В Kotlin представлены два типа строковых литералов: строки с экранированными символами и обычные строки, которые могут содержать символы новой строки и произвольный текст. Экранированная строка очень похожа на строку в Java:
Экранирование выполняется общепринятым способом, а именно с помощью обратной косой черты.
Обычная строка выделена тройной кавычкой ( «»» ), не содержит экранированных символов, но может содержать символы новой строки и любые другие символы:
Строковые шаблоны
Строки могут содержать шаблонные выражения, т.е. участки кода, которые выполняются, а полученный результат встраивается в строку. Шаблон начинается со знака доллара ($) и состоит либо из простого имени (например, переменной):
либо из произвольного выражения в фигурных скобках:




