Avatar ·

Как реализовать switch-case в Kotlin? Альтернативы и примеры

Привет! Я только начал изучать Kotlin после Java, и у меня возникла проблема. В Java я часто использовал switch-case для обработки множества условий, например: ```java int day = 3; String dayName; switch (day) { case 1: dayName = "Понедельник"; break; case 2: dayName = "Вторник"; break; case 3: dayName = "Среда"; break; case 4: dayName = "Четверг"; break; case 5: dayName = "Пятница"; break; default: dayName = "Выходной"; } ``` Но когда я попробовал написать то же самое в Kotlin, компилятор выдал ошибку — ключевое слово `switch` не определено. Я погуглил и понял, что в Kotlin нет традиционного switch-case. Вместо него используется `when`. Но я не до конца понимаю, как правильно его применять. Мне нужно: 1. Заменить простой switch-case с целыми числами. 2. Использовать when с несколькими значениями в одной ветке. 3. Обработать случай, когда нужно проверить тип объекта (например, когда переменная может быть String, Int или Boolean). 4. Использовать when как выражение (то есть присвоить результат переменной). Пожалуйста, объясните на примерах, как это работает. Особенно интересует разница между when как оператором и when как выражением. И можно ли в when использовать произвольные условия, а не только константы? Заранее спасибо! <<>>

Полное руководство по when в Kotlin: замена switch-case

Да, вы правы — в Kotlin нет оператора switch. Вместо него используется гораздо более мощная конструкция when. Она может работать и как оператор (просто выполняет блок кода), и как выражение (возвращает значение). Давайте разберём все сценарии.

1. Базовая замена switch-case

Вот как переписать ваш пример с днями недели:

fun main() {
    val day = 3
    val dayName = when (day) {
        1 -> "Понедельник"
        2 -> "Вторник"
        3 -> "Среда"
        4 -> "Четверг"
        5 -> "Пятница"
        else -> "Выходной"
    }
    println(dayName) // Выведет: Среда
}

Обратите внимание: break не нужен — Kotlin сам выходит из ветки после выполнения. else заменяет default.

2. Несколько значений в одной ветке

Если нужно объединить несколько вариантов, используйте запятую:

fun isWeekend(day: Int): String {
    return when (day) {
        1, 2, 3, 4, 5 -> "Будний день"
        6, 7 -> "Выходной"
        else -> "Неверный день"
    }
}

3. Проверка типа объекта

Это одна из самых мощных возможностей when — проверка типа с умным приведением (smart cast):

fun describe(obj: Any): String {
    return when (obj) {
        is String -> "Строка длиной ${obj.length}" // obj автоматически приведён к String
        is Int -> if (obj > 0) "Положительное число" else "Число <= 0"
        is Boolean -> "Логическое значение: $obj"
        else -> "Неизвестный тип"
    }
}

fun main() {
    println(describe("Привет")) // Строка длиной 6
    println(describe(42))       // Положительное число
    println(describe(true))     // Логическое значение: true
}

4. When как выражение (возврат значения)

Если вы используете when как выражение, ветка else обязательна, если компилятор не может доказать, что все возможные случаи покрыты:

val grade = 85
val result = when {
    grade >= 90 -> "Отлично"
    grade >= 75 -> "Хорошо"
    grade >= 60 -> "Удовлетворительно"
    else -> "Неудовлетворительно"
}
println(result) // Хорошо

Обратите внимание: здесь нет аргумента у when — мы используем произвольные условия (булевы выражения).

5. When без аргумента (произвольные условия)

Это аналог цепочки if-else if, но более читаемый:

fun classifyNumber(x: Int) {
    when {
        x < 0 -> println("Отрицательное")
        x == 0 -> println("Ноль")
        x > 0 && x % 2 == 0 -> println("Положительное чётное")
        x > 0 && x % 2 != 0 -> println("Положительное нечётное")
    }
}

6. Проверка на вхождение в диапазон (range)

fun checkAge(age: Int): String {
    return when (age) {
        in 0..12 -> "Ребёнок"
        in 13..17 -> "Подросток"
        in 18..65 -> "Взрослый"
        else -> "Пожилой"
    }
}

Важные моменты:

  • When с аргументом — проверяет равенство аргумента с константами (или другими значениями).
  • When без аргумента — просто выполняет первую истинную ветку (как if-else if).
  • When как выражение — обязательно должен быть else, если не все случаи покрыты.
  • Smart cast — после проверки is вы можете использовать свойства типа без явного приведения.

Таким образом, when полностью заменяет switch-case и даёт гораздо больше возможностей. Привыкайте использовать его — это идиоматичный способ в Kotlin.

<<>>

Альтернативный подход: использование when с sealed классами

Когда вы работаете с ограниченным набором типов (например, состояниями или командами), рекомендую использовать sealed class вместе с when. Это даёт компиляторную проверку полноты ветвей — вам не нужен else, если вы перечислили все подтипы.

sealed class Result {
    data class Success(val data: String) : Result()
    data class Error(val message: String) : Result()
    object Loading : Result()
}

fun handleResult(result: Result): String = when (result) {
    is Result.Success -> "Успех: ${result.data}"
    is Result.Error -> "Ошибка: ${result.message}"
    Result.Loading -> "Загрузка..."
    // else не нужен — все варианты покрыты
}

Если вы добавите новый подтип в sealed class, компилятор укажет, где нужно добавить ветку when. Это делает код безопаснее и предотвращает забытые сценарии. Такой подход часто используется в архитектуре приложений (например, в MVVM для обработки состояний UI).

Также для простых случаев можно использовать when с лямбдами или функции высшего порядка, но это уже экзотика. Главное — запомните: when — это мощный инструмент, который заменяет не только switch, но и многие цепочки if-else.