Spec-Zone.ru › Kotlin 1.9

Условные операторы и циклы

Оператор if

В Kotlin оператор if — это выражение: он возвращает значение. Поэтому у него нет тернарного оператора (condition ? then : else) — обычный оператор if if справляется с этой задачей.

fun main() {
    val a = 2
    val b = 3

    //sampleStart
    var max = a
    if (a < b) max = b

    // With else
    if (a > b) {
      max = a
    } else {
      max = b
    }

    // As expression
    max = if (a > b) a else b

    // You can also use `else if` in expressions:
    val maxLimit = 1
    val maxOrLimit = if (maxLimit > a) maxLimit else if (a > b) a else b

    //sampleEnd
    println("max is $max")
    println("maxOrLimit is $maxOrLimit")
}

Ветви выражения 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 имеет тип 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")
}

Вы также можете проверить, является ли значение частью диапазона или коллекции.

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")
}

Другой вариант — проверка того, что значение принадлежит или не принадлежит какому-либо типу. Обратите внимание, что из-за интеллектуальных приведений типов вы можете обращаться к методам и свойствам типа без дополнительных проверок.

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, ограничена телом этого оператора.

Циклы 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 в циклах. См. Возвращение и переходы.

Последнее изменение: 11 мая 2023
Проверка и приведение типов Возвращение и переходы

© 2010–2023 JetBrains s.r.o. and Kotlin Programming Language contributors
Licensed under the Apache License, Version 2.0.
https://kotlinlang.org/docs/control-flow.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API