Условные операторы и циклы
Оператор if
В Kotlin, if является выражением: оно возвращает значение. Поэтому оператора тернарного условия (condition ? then : else) нет, так как обычный if прекрасно подходит для этой роли.
var max = a
if (a < b) max = b
// With else
var max: Int
if (a > b) {
max = a
} else {
max = b
}
// As expression
val max = if (a > b) a else b
Ветви оператора if могут быть блоками. В этом случае, значением блока является последнее выражение в нём:
val max = if (a > b) {
print("Choose a")
a
} else {
print("Choose b")
b
}
Если вы используете if как выражение, например, для возврата его значения или присваивания его переменной, то ветвь else является обязательной.
Оператор when
when определяет условное выражение с несколькими ветвями. Он похож на оператор switch в языках C-семейства. Его простая форма выглядит так.
when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> {
print("x is neither 1 nor 2")
}
}
when последовательно сравнивает свой аргумент со всеми ветвями, пока не удовлетворит какое-то условие ветви.
when может использоваться как выражение, так и как оператор. Если он используется как выражение, то значение первой подходящей ветви становится значением всего выражения. Если он используется как оператор, то значения отдельных ветвей игнорируются. Как и в случае с if, каждая ветвь может быть блоком, а её значением является значение последнего выражения в блоке.
Ветвь else выполняется, если ни одно из других условий ветвей не выполняется.
Если when используется как выражение, то ветвь else является обязательной, за исключением случаев, когда компилятор может доказать, что все возможные варианты покрыты условиями ветвей, например, с записями класса enum и подтипами класса sealed.
enum class Bit {
ZERO, ONE
}
val numericValue = when (getRandomBit()) {
Bit.ZERO -> 0
Bit.ONE -> 1
// 'else' is not required because all cases are covered
}
В when операторах, ветвь else является обязательной при следующих условиях:
whenимеет типBoolean,enum, илиsealed, или их nullable аналоги.ветви
whenне покрывают все возможные случаи для данного объекта.
enum class Color {
RED, GREEN, BLUE
}
when (getColor()) {
Color.RED -> println("red")
Color.GREEN -> println("green")
Color.BLUE -> println("blue")
// 'else' is not required because all cases are covered
}
when (getColor()) {
Color.RED -> println("red") // no branches for GREEN and BLUE
else -> println("not red") // 'else' is required
}
Для определения общего поведения для нескольких случаев объедините их условия в одной строке через запятую:
when (x) {
0, 1 -> print("x == 0 or x == 1")
else -> print("otherwise")
}
Вы можете использовать произвольные выражения (а не только константы) в качестве условий ветвей
when (x) {
s.toInt() -> print("s encodes x")
else -> print("s does not encode x")
}
Вы также можете проверить значение на принадлежность in или !in к диапазону или коллекции:
when (x) {
in 1..10 -> print("x is in the range")
in validNumbers -> print("x is valid")
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}
Другой вариант - проверить, что значение is или !is принадлежит определённому типу. Обратите внимание, что благодаря умным приведениям типов, вы можете обращаться к методам и свойствам типа без дополнительных проверок.
fun hasPrefix(x: Any) = when(x) {
is String -> x.startsWith("prefix")
else -> false
}
when также может использоваться как замена цепочки if-else if . Если аргумент не указан, условия ветвей являются простыми булевыми выражениями, и ветвь выполняется, когда её условие истинно:
when {
x.isOdd() -> print("x is odd")
y.isEven() -> print("y is even")
else -> print("x+y is odd")
}
Вы можете захватить объект when в переменную с помощью следующего синтаксиса:
fun Request.getBody() =
when (val response = executeRequest()) {
is Success -> response.body
is HttpError -> throw HttpException(response.status)
}
Область действия переменной, введённой в объекте when, ограничена телом этого when.
Циклы for
Цикл for перебирает всё, что предоставляет итератор. Это эквивалентно циклу foreach в языках вроде C#. Синтаксис цикла for следующий:
for (item in collection) print(item)
Тело цикла for может быть блоком.
for (item: Int in ints) {
// ...
}
Как упоминалось ранее, for перебирает всё, что предоставляет итератор. Это означает, что:
-
у него есть член или функция-расширение
iterator(), которая возвращаетIterator<>:у него есть член или функция-расширение
next()у него есть член или функция-расширение
hasNext(), которая возвращаетBoolean.
Все эти три функции должны быть помечены как operator.
Для перебора диапазона чисел используйте выражение диапазона:
fun main() {
//sampleStart
for (i in 1..3) {
println(i)
}
for (i in 6 downTo 0 step 2) {
println(i)
}
//sampleEnd
}
Цикл for по диапазону или массиву компилируется в цикл по индексу, не создавая объект итератора.
Если вы хотите перебрать массив или список с индексом, вы можете сделать это так:
fun main() {
val array = arrayOf("a", "b", "c")
//sampleStart
for (i in array.indices) {
println(array[i])
}
//sampleEnd
}
В качестве альтернативы, вы можете использовать функцию-библиотеку withIndex:
fun main() {
val array = arrayOf("a", "b", "c")
//sampleStart
for ((index, value) in array.withIndex()) {
println("the element at $index is $value")
}
//sampleEnd
}
Циклы while
Циклы while и do-while выполняют своё тело непрерывно, пока их условие выполняется. Разница между ними заключается во времени проверки условия:
whileпроверяет условие и, если оно выполняется, выполняет тело, а затем возвращается к проверке условия.do-whileвыполняет тело, а затем проверяет условие. Если оно выполняется, цикл повторяется. Таким образом, телоdo-whileвыполняется как минимум один раз независимо от условия.
while (x > 0) {
x--
}
do {
val y = retrieveData()
} while (y != null) // y is visible here!
Операторы break и continue в циклах
Kotlin поддерживает традиционные операторы break и continue в циклах. См. Возвращение и переходы.
© 2010–2022 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/control-flow.html