Условные операторы и циклы
Оператор 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 определенного типа. Обратите внимание, что из-за smart-кастов вы можете получить доступ к методам и свойствам типа без дополнительных проверок.
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