Kotlin Academy · Урок

Исчерпывающий when

Обрабатывайте все варианты

Урок 4 из 413 шагов

«Исчерпывающий when» — бесплатный урок Kotlin Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Kotlin Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Kotlin Academy содержит 4 уроков всего.

Охват всех случаев

Исчерпывающий when обрабатывает каждое возможное значение. При использовании в качестве выражения Kotlin требует этого, чтобы результат формировался всегда.

В этом уроке показано, как сделать when исчерпывающим и почему это полезно.

Ветвь «иначе» делает конструкцию исчерпывающей

Для объектов с открытым набором значений, таких как Int, ветвь else охватывает всё, что не перечислено.

Это гарантирует, что конструкция when всегда найдёт подходящий вариант.

fun label(n: Int): String = when (n) {
    0 -> "zero"
    1 -> "one"
    else -> "many"
}

fun main() {
    println(label(0))
    println(label(5))
}

Перечисления обеспечивают полноту

Для перечисления компилятор знает все возможные значения. Перечислите их все — и else можно не указывать.

enum class Direction { NORTH, SOUTH, EAST, WEST }

fun turn(d: Direction): String = when (d) {
    Direction.NORTH -> "up"
    Direction.SOUTH -> "down"
    Direction.EAST -> "right"
    Direction.WEST -> "left"
}

fun main() {
    println(turn(Direction.EAST))
}

Пропущен вариант перечисления

Если в выражении when забыть значение перечисления, компилятор сообщит об ошибке.

Так обнаруживаются ошибки сразу после добавления новой константы перечисления.

enum class Status { ACTIVE, PAUSED, STOPPED }

fun describe(s: Status): String = when (s) {
    Status.ACTIVE -> "running"
    Status.PAUSED -> "paused"
    Status.STOPPED -> "stopped"
}

fun main() {
    println(describe(Status.PAUSED))
}

Запечатанные классы

Запечатанный класс имеет фиксированный набор подклассов, известных во время компиляции.

Благодаря этому конструкция when может охватить все подтипы без else.

sealed class Shape
class Circle(val r: Double) : Shape()
class Square(val s: Double) : Shape()

fun area(shape: Shape): Double = when (shape) {
    is Circle -> 3.14159 * shape.r * shape.r
    is Square -> shape.s * shape.s
}

fun main() {
    println(area(Square(4.0)))
}

Зачем нужна полнота

Исчерпывающая конструкция when превращает пропущенные варианты в ошибки компиляции, а не в незаметные ошибки.

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

Для инструкций полнота не обязательна

Если конструкция when используется как инструкция, а не присваивается переменной, она не обязана быть исчерпывающей.

Но для перечислений и запечатанных типов всё равно рекомендуется охватывать все варианты.

enum class Light { RED, GREEN }

fun main() {
    val light = Light.RED
    when (light) {
        Light.RED -> println("stop")
        Light.GREEN -> println("go")
    }
}

Объединение запечатанных классов и классов данных

В запечатанных иерархиях часто используют подклассы — классы данных. Это даёт исчерпывающее сопоставление и умные приведения типов для доступа к свойствам.

sealed class Result
data class Ok(val value: Int) : Result()
data class Err(val message: String) : Result()

fun show(r: Result): String = when (r) {
    is Ok -> "ok: " + r.value
    is Err -> "error: " + r.message
}

fun main() {
    println(show(Ok(42)))
    println(show(Err("boom")))
}

Ветвь «иначе» как страховка

В конструкцию when для запечатанного типа или перечисления всё ещё можно добавить else, но тогда компилятор перестанет предупреждать о новых вариантах.

Если не указывать else, сохраняется безопасность на этапе компиляции, поэтому для закрытых типов предпочтительнее обходиться без неё.

enum class Coin { HEADS, TAILS }

fun flip(c: Coin): Int = when (c) {
    Coin.HEADS -> 1
    Coin.TAILS -> 0
}

fun main() {
    println(flip(Coin.HEADS))
}

Логический тип и объекты с закрытым набором значений

У типа Boolean всего два значения, поэтому при перечислении обоих конструкция when становится исчерпывающей без else.

fun yesNo(flag: Boolean): String = when (flag) {
    true -> "yes"
    false -> "no"
}

fun main() {
    println(yesNo(true))
    println(yesNo(false))
}

Объединяем всё вместе

Исчерпывающая конструкция when означает, что охвачены все варианты:

  • else охватывает объекты с открытым набором значений, такие как Int
  • Перечисления, запечатанные классы и Boolean могут быть исчерпывающими без else
  • При добавлении новых вариантов компилятор указывает на пропущенные
sealed class Event
object Start : Event()
object Stop : Event()

fun handle(e: Event): String = when (e) {
    is Start -> "starting"
    is Stop -> "stopping"
}

fun main() {
    println(handle(Start))
    println(handle(Stop))
}

Быстрая проверка

Проверьте, насколько хорошо Вы поняли исчерпывающие конструкции when.

Итоги

Вы научились делать конструкцию when исчерпывающей:

  • else обрабатывает объекты с открытым набором значений
  • Перечисления, запечатанные классы и Boolean можно полностью охватить
  • Проверки во время компиляции обнаруживают пропущенные варианты

На этом завершается курс «Выражения выбора и умные приведения типов».

Можно начать бесплатно

Изучай Kotlin с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
51
Уроки
203

Часто задаваемые вопросы

Урок «Исчерпывающий when» бесплатный?

Да — полный текст урока «Исчерпывающий when» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Kotlin Academy, подпишись на CoddyKit PRO. Курс Kotlin Academy содержит 4 уроков всего.

Чему я научусь в уроке «Исчерпывающий when»?

Обрабатывайте все варианты Ты практикуешь Kotlin Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Kotlin Academy?

Предыдущий опыт не требуется. Kotlin Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.

Сколько времени занимает урок «Исчерпывающий when»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Kotlin Academy?

Да. Каждый урок Kotlin Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. when как выражение
  2. Умные приведения типов
  3. Операторы is и as
  4. Исчерпывающий when
← Назад к Kotlin Academy