Avatar ·

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

Привет, коллеги! Я только начал изучать Kotlin после Java и столкнулся с проблемой: в Kotlin нет привычного оператора switch-case. В Java я часто использовал его для обработки разных значений одной переменной, например, для выбора действия в зависимости от дня недели или статуса заказа. Вот как я писал на Java: ```java int day = 3; String dayName; switch (day) { case 1: dayName = "Понедельник"; break; case 2: dayName = "Вторник"; break; case 3: dayName = "Среда"; break; default: dayName = "Неизвестный день"; } ``` Когда я попробовал написать то же самое в Kotlin, компилятор выдал ошибку: "Unresolved reference: switch". Я погуглил и узнал, что в Kotlin вместо switch-case используется when. Но примеры, которые я нашёл, выглядят сложнее, чем я ожидал. Например, я видел, что when можно использовать без аргументов, с разными типами и даже с диапазонами. Мой конкретный вопрос: как правильно заменить switch-case на when в Kotlin? Нужно ли писать break (как в Java), или when сам выходит из блока? Можно ли использовать when для проверки не только чисел, но и строк, и других типов? И что делать, если мне нужно выполнить несколько действий для одного case? Буду благодарен за простой и понятный пример с пояснениями. Я хочу понять, как это работает, чтобы не путаться в будущем. <<>>

Полная замена switch-case на when в Kotlin

В Kotlin нет оператора switch, но его роль полностью выполняет конструкция when. Она гораздо мощнее и гибче, чем switch в Java. Главное отличие: break не нужен — when автоматически выходит после первого совпадения. Ниже разберём все сценарии.

1. Базовый синтаксис (как switch для чисел)

Ваш пример на Java в Kotlin будет выглядеть так:

val day = 3
val dayName = when (day) {
    1 -> "Понедельник"
    2 -> "Вторник"
    3 -> "Среда"
    else -> "Неизвестный день"
}
println(dayName) // Среда

Объяснение:

  • После when (переменная) идут ветки (case).
  • Каждая ветка: значение -> результат.
  • else — аналог default в Java. Обязателен, если вы присваиваете результат (как в примере).
  • Можно не присваивать результат, а просто выполнять действия: when (x) { 1 -> println("Один") }.

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

Если нужно выполнить одно действие для нескольких case, перечислите их через запятую:

val x = 2
when (x) {
    1, 2 -> println("x равно 1 или 2")
    3 -> println("x равно 3")
    else -> println("x не 1, 2 или 3")
}

3. Использование диапазонов и условий

when поддерживает проверку на вхождение в диапазон (in) и произвольные логические условия:

val number = 15
val description = when (number) {
    in 1..10 -> "Число от 1 до 10"
    in 11..20 -> "Число от 11 до 20"
    else -> "Число больше 20 или меньше 1"
}
println(description) // Число от 11 до 20

А ещё можно проверять тип объекта (замена instanceof):

val obj: Any = "Hello"
val result = when (obj) {
    is String -> "Строка длиной ${obj.length}"
    is Int -> "Целое число"
    else -> "Другой тип"
}

4. when без аргумента (как замена if-else)

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

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

Это удобно, когда условие сложное или зависит от разных переменных.

5. Важные нюансы

  • Без break: В Kotlin when не проваливается (fall-through) в следующую ветку. Если нужно выполнить несколько действий — используйте блок {}: 1 -> { println("Один"); doSomething() }.
  • Типы данных: when работает с любыми типами: Int, String, Enum, Boolean, Any и т.д.
  • Проверка на null: Можно использовать null как одно из значений: when (x) { null -> ... }.

Итог: when — это не просто замена switch, а более выразительная конструкция. Она делает код короче и безопаснее (нет забытых break). Начните с простых примеров, а затем осваивайте диапазоны и проверку типов.

<<>>

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

Если вы работаете с фиксированным набором значений (например, статусы заказа, дни недели), лучше всего использовать enum class в паре с when. Это делает код более типобезопасным и читаемым.

Пример с enum

enum class Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

fun getDayType(day: Day): String {
    return when (day) {
        Day.MONDAY, Day.TUESDAY, Day.WEDNESDAY, Day.THURSDAY, Day.FRIDAY -> "Будний день"
        Day.SATURDAY, Day.SUNDAY -> "Выходной"
    }
}

// Использование
println(getDayType(Day.SATURDAY)) // Выходной

Почему это удобно?

  • Компилятор проверяет, что вы обработали все значения enum (если не обработали — будет ошибка).
  • Не нужен else, если перечислены все варианты.
  • Код самодокументируется: сразу видно, какие значения возможны.

Когда это полезно?

Для любых конечных списков: статусы (NEW, PROCESSING, SHIPPED, DELIVERED), типы пользователей (ADMIN, USER, MODERATOR), цвета и т.д. Это заменяет не только switch, но и делает код более надёжным.