Идиомы
Сборник случайных и часто используемых идиом в Kotlin. Если у вас есть любимая идиома, внесите её, отправив запрос на добавление.
Создание DTO (POJO/POCO)
data class Customer(val name: String, val email: String)
предоставляет класс Customer со следующей функциональностью:
геттеры (и сеттеры в случае
var) для всех свойствequals()hashCode()toString()copy()component1(),component2(), ..., для всех свойств (см. Классы данных)
Значения по умолчанию для параметров функций
fun foo(a: Int = 0, b: String = "") { ... }
Фильтрация списка
val positives = list.filter { x -> x > 0 }
Или, как альтернативу, ещё короче:
val positives = list.filter { it > 0 }
Узнайте разницу между фильтрацией в Java и Kotlin.
Проверка наличия элемента в коллекции
if ("john@example.com" in emailsList) { ... }
if ("jane@example.com" !in emailsList) { ... }
Интерполяция строк
println("Name $name")
Узнайте разницу между конкатенацией строк в Java и Kotlin.
Проверка типов объектов
when (x) {
is Foo -> ...
is Bar -> ...
else -> ...
}
Список только для чтения
val list = listOf("a", "b", "c")
Словарь только для чтения
val map = mapOf("a" to 1, "b" to 2, "c" to 3)
Доступ к элементу словаря
println(map["key"]) map["key"] = value
Проход по словарю или списку пар
for ((k, v) in map) {
println("$k -> $v")
}
k и v могут быть любыми удобными именами, такими как name и age.
Итерация по диапазону
for (i in 1..100) { ... } // closed range: includes 100
for (i in 1 until 100) { ... } // half-open range: does not include 100
for (x in 2..10 step 2) { ... }
for (x in 10 downTo 1) { ... }
(1..10).forEach { ... }
Отложенное свойство
val p: String by lazy {
// compute the string
}
Расширяющие функции
fun String.spaceToCamelCase() { ... }
"Convert this to camelcase".spaceToCamelCase()
Создание синглтона
object Resource {
val name = "Name"
}
Создание экземпляра абстрактного класса
abstract class MyAbstractClass {
abstract fun doSomething()
abstract fun sleep()
}
fun main() {
val myObject = object : MyAbstractClass() {
override fun doSomething() {
// ...
}
override fun sleep() { // ...
}
}
myObject.doSomething()
}
Краткая запись для проверки на не-null
val files = File("Test").listFiles()
println(files?.size) // size is printed if files is not null
Краткая запись для проверки на не-null с альтернативой
val files = File("Test").listFiles()
println(files?.size ?: "empty") // if files is null, this prints "empty"
// To calculate the fallback value in a code block, use `run`
val filesSize = files?.size ?: run {
return someSize
}
println(filesSize)
Выполнение оператора при null
val values = ...
val email = values["email"] ?: throw IllegalStateException("Email is missing!")
Получение первого элемента из потенциально пустой коллекции
val emails = ... // might be empty val mainEmail = emails.firstOrNull() ?: ""
Узнайте разницу между получением первого элемента в Java и Kotlin.
Выполнение, если не null
val value = ...
value?.let {
... // execute this block if not null
}
Преобразование значения, если оно не null
val value = ...
val mapped = value?.let { transformValue(it) } ?: defaultValue
// defaultValue is returned if the value or the transform result is null.
Возврат в операторе when
fun transform(color: String): Int {
return when (color) {
"Red" -> 0
"Green" -> 1
"Blue" -> 2
else -> throw IllegalArgumentException("Invalid color param value")
}
}
Оператор try-catch
fun test() {
val result = try {
count()
} catch (e: ArithmeticException) {
throw IllegalStateException(e)
}
// Working with result
}
Оператор if
val y = if (x == 1) {
"one"
} else if (x == 2) {
"two"
} else {
"other"
}
Использование методов, возвращающих Unit, в стиле билдера
fun arrayOfMinusOnes(size: Int): IntArray {
return IntArray(size).apply { fill(-1) }
}
Функции с единственным выражением
fun theAnswer() = 42
Это эквивалентно
fun theAnswer(): Int {
return 42
}
Это можно эффективно комбинировать с другими идиомами, что приводит к более короткому коду. Например, с выражением when.
fun transform(color: String): Int = when (color) {
"Red" -> 0
"Green" -> 1
"Blue" -> 2
else -> throw IllegalArgumentException("Invalid color param value")
}
Вызов нескольких методов на объекте с помощью with
class Turtle {
fun penDown()
fun penUp()
fun turn(degrees: Double)
fun forward(pixels: Double)
}
val myTurtle = Turtle()
with(myTurtle) { //draw a 100 pix square
penDown()
for (i in 1..4) {
forward(100.0)
turn(90.0)
}
penUp()
}
Настройка свойств объекта с помощью apply
val myRectangle = Rectangle().apply {
length = 4
breadth = 5
color = 0xFAFAFA
}
Это полезно для настройки свойств, которые отсутствуют в конструкторе объекта.
Try-with-resources Java 7
val stream = Files.newInputStream(Paths.get("/some/file.txt"))
stream.buffered().reader().use { reader ->
println(reader.readText())
}
Обобщенная функция, требующая информацию о типе обобщения
// public final class Gson {
// ...
// public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {
// ...
inline fun <reified T: Any> Gson.fromJson(json: JsonElement): T = this.fromJson(json, T::class.java)
Переменная Boolean, которая может быть null
val b: Boolean? = ...
if (b == true) {
...
} else {
// `b` is false or null
}
Перестановка двух переменных
var a = 1
var b = 2
a = b.also { b = a }
Отметить код как неполный (TODO)
Стандартная библиотека Kotlin имеет функцию TODO(), которая всегда вызывает исключение NotImplementedError. Её тип возвращаемого значения Nothing, поэтому она может использоваться независимо от ожидаемого типа. Также есть перегрузка, принимающая параметр причины:
fun calcTaxes(): BigDecimal = TODO("Waiting for feedback from accounting")
Плагин kotlin для IntelliJ IDEA понимает семантику TODO() и автоматически добавляет указатель на код в окно TODO.
Что дальше?
Решите задачи Advent of Code в стиле idiomatic Kotlin
Научитесь выполнять типичные задачи со строками в Java и Kotlin
© 2010–2022 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/idioms.html