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

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

Kotlin

Любой кот линяет. Из выпавшей шерсти можно собрать второго кота. По такой же аналогии из Java можно создать новый язык Kotlin, образованный из двух слов Kot linяет. Есть ещё неправдоподобная версия об острове в Финском заливе, которая просто смешна и не заслуживает внимания.

Kotlin

17 мая 2017 года на Google IO объявили о поддержке Kotlin в Android Studio 3.0. Пора учить новый язык, который заслужил много лестных отзывов от опытных разработчиков.

Что нового

28 ноября 2017 года вышла новая версия Kotlin 1.2. Список новинок здесь.

Добавлены новые функции для изменяемых списков: fill, replaceAll, shuffle.

Добавлена новая функция shuffled для неизменяемых списков.

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


val item = -100
println("${item.sign}") // вернёт -1

Базовые принципы

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

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

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


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

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

Можно сразу вызывать 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 = "нет ответа"

Защита от null

В Java существует проблема с исключением NullPointerException и разработчику нужно постоянно устраивать проверки на null. В Kotlin существует защита от подобных ошибок.


// Не скомпилируется. Кот не может быть null
var notNullCat: Cat = null
// Кот может быть null
var cat: Cat? = null

// Не скомпилируется, кот может быть null и мы должны учитывать это
cat.print()

// Можем печатать, если cat != null
cat?.print()
// Умное приведение. Если мы проводили проверку if, то можно вызывать обычным способом
// checked nullity
if (cat != null) {
    cat.print()
}

// Если уверены, что объект не null. Иначе выбросит исключение
cat!!.print()

// Используйте элвис-оператор, чтобы дать альтернативное значение, если объект равен null
val name = cat?.name ?: "empty"

Любой объект может быть null и мы можем явно указать это через символ вопроса ?. В этом случае Kotlin будет проверять на возможность ошибки и предупреждать на этапе разработки.

Умное приведение Smart cast позволяет превратить переменную из одного состояния в другое: cat? превратится в cat (см. пример выше) или переменная a типа Int? превратится в Int.


val a: Int? = null

if (a != null) {
    a.toLong() // теперь это Int
}

Если умное приведение вам не нужно, то используйте запись с безопасным оператором ?.


val a: Int? = null

a?.toLong()

Другой "Элвис-оператор" ?: (напоминает причёску Элвиса Пресли, если повернуть голову, как на смайликах) позволяет назначить альтернативное значение, если объект равен null.


val a: Int? = null

val myLong = a?.toLong() ?: 0L

Справа от элвис-оператора можно использовать return и выбрасывать исключения.


val myLong = a?.toLong() ?: return false

val myLong = a?.toLong() ?: throw IllegalStateException()

Если вы точно уверены, что ваша переменная не null, то можете использовать оператор !!. Kotlin будет полагаться на ваш профессионализм и не станет проверять ваше предположение. Если вы ошиблись в своём предположении, то ваше приложение может грохнуться.


// скомпилируется, но приложение грохнется
val a: Int? = null
a!!.toLong()

Например, в Android часто объявляются компоненты, а инициализация происходит позже.


// объявляем
var button: Button? = null

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

	// инициализируем
    button = findViewById(R.id.button)
	
	button?.setOnClickListener(View.OnClickListener {  })
}

Подобный способ позволяет избежать null и аналогичен записи в Java.


if (button != null) {
    button.setOnClickListener(/* Ваш код */);
}

При полной уверенности можете написать


button!!.setOnClickListener { /* */ }

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

Иногда переменную нельзя сразу инициализировать, сделать это можно чуть позже. Для таких случаев придумали новый модификатор lateinit (отложенная инициализация).


private lateinit var button: Button

Переменная обязательно должна быть изменяемой (var). Не должна относиться к примитивным типам (Int, Double, Float и т.д). Не должна иметь собственных геттеров/сеттеров.

Подобный подход удобен во многих случаях, избегая проверки на null. Если вы обратитесь к переменной до её инициализации, то получите исключение "lateinit property ... hos not been initialized" вместо NullPointerException.

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

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

Ключевое слово by lazy


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

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

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


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

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

Продолжить изучение Kotlin

Сконвертировать существующий Java-код на Kotlin можно через меню Code | Convert Java File to Kotlin File.

Если скопировать в буфер обмена код на Java и вставить его в kt-файл, то студия автоматически сконвертирует код.

На заметку: Файлы с кодом на Kotlin смотрятся странно в папке java в проекте студии. Открываем файл gradle.build модуля и в секции android добавляем блок:


sourceSets {
    main.java.srcDirs += 'src/main/kotlin'
}

Переключаемся в режим Project и переименовываем папку java. Приложение будет работать по-прежнему. В режиме Android по-прежнему будет видна папка java, это жестко прописано в студии. Может потом поправят этот момент.

Tools | Kotlin

Также в студии есть целый раздел меню для настройки: Tools | Kotlin.

Show Kotlin Bytecode

При выборе Show Kotlin Bytecode можно просматривать любой файл *.kt, в отдельном окне будет виден байткод файла. Если в нём не будет данных, которых нельзя представить в Java, то также будет доступна возможность декомпилировать его в Java-код кнопкой Decompile.

Kotlin REPL

Интересная оболочка в виде командной строки. Можно быстро написать какое-то выражение и получить результат.

Anko

Библиотека Anko была специально разработана для удобного программирования под Android, сокращая количество кода для вызовов намерений, диалоговых окон, журналирования и т.д.


//Java
Toast.makeText(context, "Hello Kitty!", Toast.LENGTH_SHORT).show();

//Anko Kotlin
toast("Hello Kitty!")

// Java style
val intent = Intent(this, SecondActivity::class.java)
startActivity(intent)

// Anko
startActivity<SecondActivity>()

// Anko Intent для звонка
makeCall("911")

Примеры на Kotlin

Android KTX

Hello Kitty

Щелчок кнопки/Счётчик ворон

Переключение между экранами приложения

Счётчик шагов

ShareActionProvider (Провайдер действия передачи информации)

Android: ValueAnimator

RxKotlin

Книги

На русском языке доступна книга Kotlin в действии.

В начале книге перечисляются благодарности, в том числе - Наконец, мы хотели бы поблагодарить наши семьи и котов за то, что они делают этот мир лучше.

Реклама