ПрограммированиеKotlin разработчик

Что такое конструкция when в Kotlin, как она работает, чем отличается от switch-case в Java и какие возможности предоставляет для обработки различных ситуаций? Приведите примеры различных случаев использования.

Проходите собеседования с ИИ помощником Hintsage

Ответ.

Конструкция when в Kotlin — это мощный инструмент для управления потоком выполнения программы, пришедший на смену традиционному switch-case из Java. when был введён для увеличения выразительности, сокращения boilerplate-кода и повышения безопасности типов.

История вопроса

В Java конструкция switch-case ограничена только определёнными типами (enum, int, String). В отличие от Java, разработчики Kotlin стремились упростить условные ветвления, сделав их более выразительными и безопасными.

Проблема

Ограничения switch-case в Java затрудняют расширение и сопровождаемость кода, особенно при работе с коллекциями, сравнением диапазонов или обработкой различных типов.

Решение

Конструкция when в Kotlin универсальна: она работает как выражение (может возвращать значение), поддерживает проверки условий, диапазонов, отдельных значений, типов и комбинирование условий.

Пример кода:

fun describe(obj: Any): String = when (obj) { 1 -> "One" in 2..10 -> "From two to ten" is String -> "String with length ${obj.length}" else -> "Unknown" } val res1 = describe(1) // "One" val res2 = describe(5) // "From two to ten" val res3 = describe("Kotlin") // "String with length 6" val res4 = describe(42.0) // "Unknown"

Ключевые особенности:

  • Возможность работать как с выражениями, так и с операторами.
  • Проверка по значению, типу, диапазону и сложным условиям.
  • Обеспечение безопасности при обработке всех вариантов (например, с sealed-классами).

Вопросы с подвохом.

Может ли when использоваться без аргумента?

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

when { x < 0 -> println("Negative") x == 0 -> println("Zero") else -> println("Positive") }

Обязателен ли блок else в конструкции when?

Блок else не обязателен, если обработаны все возможные случаи, например, для enum или sealed class. Но если есть вероятность некрытого случая, else обязателен для избежания ошибок времени компиляции.

sealed class Fruit object Apple : Fruit() object Pear : Fruit() fun check(f: Fruit): String = when (f) { Apple -> "It's an apple" Pear -> "It's a pear" // Нет блока else, и компилятор не ругается — все варианты учтены }

Можно ли в when использовать несколько значений в одной ветке?

Да, несколько значений можно объединять через запятую.

when (value) { 0, 1 -> println("Zero or One") else -> println("Other") }

Типовые ошибки и анти-паттерны

  • Пропуск блока else при не полных вариантах (может привести к ошибкам времени выполнения).
  • Перегрузка when слишком сложными ветками (нарушение читаемости).
  • Использование when только как switch-case, без применения проверки типов и диапазонов.

Пример из жизни

Негативный кейс

В платежной системе switch-case используется для определения статуса операции. При добавлении нового типа статуса забыли обновить switch. Необработанный статус приводит к silent-error.

Плюсы:

  • Быстрая реализация изменений при небольшом количестве статусов.

Минусы:

  • Нет гарантии, что все статусы учтены.
  • Неявные silent-ошибки при появлении новых значений.

Позитивный кейс

В Kotlin используется sealed class для статусов и конструкция when для их обработки. При добавлении нового статуса компилятор требует добавить обработку нового случая.

Плюсы:

  • Безопасная обработка всех статусов.
  • Ошибка компиляции при пропуске кейса.

Минусы:

  • Необходимость в тщательном обновлении sealed class при расширении системы.