Освой Kotlin играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Быстрое вступление

Исходный код хранится в файлах с расширением .kt (почему не .kot?).

В языке используется "кошачий принцип" - чем меньше печатаешь код, тем больше времени останется на сон.

Например, необязательно ставить точку с запятой в конце выражения. Так поступает JavaScript и многие новые языки программирования.


// и так сойдёт
val x = 1
val y = 2
В Kotlin есть единственное место, где точка с запятой обязательна - в перечислении enum

Необязательно объявлять тип переменной, если из контекста понятно её предназначение. Если брать предыдущий пример, то по значению 1 можно догадаться, что переменная является типом Int.

Узнать тип переменной в студии можно через комбинацию клавиш Ctrl+Shift+P

Kotlin не делит типы на примитивные и их обёртки. Например, есть тип Int вместо int и Integer.

Можно сразу вызывать println вместо длинного System.out.println. Стандартная библиотека Kotlin включает в себя популярные методы Java для быстрого доступа.

Например, можно быстро получить содержимое файла с сервера через метод URL.readText():


// не вызывать в основном потоке!
val address = "http://example.com"
val someText = URL(address).readText()

Объявление переменных

В Java мы сначала указываем тип переменной, а потом её имя. В Kotlin немного не так. Сначала вы указываете ключевое слово val или var, затем имя переменной и по желанию можете указать тип переменной.


val kitty = "Васька"
val age = 7
// необязательно, но укажем тип
val weight: Int = 3
val catName: String = "Мурзик"

val actionBar = supportActionBar // объект ActionBar в активности без new

Если вы не инициализируете переменную, то тип указать нужно обязательно.


val age: Int
age = 7

Иногда тип указывать обязательно.


val a: Any = 12
val context: Context = activity

Ключевое слово val (от слова value) ссылается на неизменяемую переменную, что соответствует ключевому слову final в Java.


// Java
final String name = "Васька";

// Kotlin
val name = "Васька"

А часто используемое выражение в Java можно заменить на конструкцию с ключевым словом const (применимо только к базовым типам):


// Java
public static final String CAT_TALK = "meow";

// Kotlin
const val CAT_TALK = "meow"

Для обычных изменяемых переменных используется ключевое слово var (от слова variable).

Рекомендуется всегда использовать val, если это позволяет логика программы.

При этом нужно помнить, что хотя ссылка val неизменяема, сам объект может быть изменяемым:


val cats = arrayListOf("Васька")
cats.add("Барсик")

При использовании var вы можете не указывать тип переменной, но это не значит, что вы можете использовать его не по назначению, это вам не PHP.


var answer = 42
// так нельзя
answer = "нет ответа"

Ключевое слово inline

Ещё одно новое ключевое слово в Kotlin.

Ключевое слово by lazy (отложенная инициализация)

Ключевое слово by lazy служет для отложенной инициализации через механизм делегатов. Делегат lazy принимает лямбда-выражение с кодом, который вы бы хотели выполнить для инициализации свойства.


val infoTextView by lazy { view!!.findViewById<TextView>(R.id.textView) }

lateinit (поздняя инициализация)

Ключевое слово lateinit служит для поздней инициализации. В любое объявление var-свойства можно добавить ключевое слово lateinit. Тогда Kotlin позволит отложить инициализацию свойства до того момента, когда такая возможность появится. Это полезная возможность, но её следует применять осторожно. Если переменная с поздней инициализацией получит начальное значение до первого обращения к ней, проблем не будет. Но если сослаться на такое свойство до его инициализации, то получим исключение UninitializedPropertyAccessException. Как вариант, можно использовать тип с поддержкой null, но тогда придётся обрабатывать возможное значение null по всему коду. Получив начальное значение, переменные с поздней инициализацией будут работать так же, как другие переменные.

Для проверки факта инициализации переменной вызывайте метод isInitialized(). Функцию следует использовать экономно — не следует добавлять эту проверку к каждой переменной с поздней инициализацией. Если вы используете isInitialized() слишком часто, то скорее всего вам лучше использовать тип с поддержкой null.

Псевдоним для импорта

Чтобы не путаться с именами классов из разных пакетов, можно присвоить новый псевдоним.


import android.os.Bundle
import ru.alexanderklimov.cat.Bundle as CatBundle

fun getBundle() {
    val bundle1 = Bundle()
    val bundle2 = CatBundle()
}

Исключения

Создадим собственное исключение.


class CustomException(message:String): Exception(message)

Теперь можем кинуть созданное исключение в своём коде в нужном месте.


throw CustomException("Threw custom exception")
Реклама