Avatar ·

Как использовать WHEN в Kotlin для сравнения чисел с операторами <, <=, >, >=?

Всем привет! Я недавно начал изучать Kotlin и столкнулся с проблемой. Я пытаюсь использовать конструкцию `when` для проверки диапазона чисел, но не понимаю, как правильно применять операторы сравнения (<, <=, >, >=). Вот что я пробовал: ```kotlin val score = 85 when (score) { < 60 -> println("Неудовлетворительно") 60..70 -> println("Удовлетворительно") 71..85 -> println("Хорошо") > 85 -> println("Отлично") } ``` Но компилятор выдаёт ошибку на строках с `< 60` и `> 85`. Я понимаю, что `when` обычно работает с точными значениями или диапазонами через `..`, но что делать, если нужно сравнить с помощью операторов? Можно ли вообще так делать в Kotlin, или нужно использовать `if-else`? Я видел, что в Java есть `switch`, но там тоже нельзя использовать сравнения. Но в Kotlin `when` гораздо мощнее, и мне кажется, должно быть решение. Подскажите, как правильно написать такой код? Заранее спасибо! <<>>

Проблема: почему ваш код не работает

Вы правы — when в Kotlin действительно мощнее, чем switch в Java, но он не принимает операторы сравнения напрямую в виде < 60 или > 85. В Kotlin when ожидает либо конкретные значения, либо выражения, которые возвращают Boolean. Оператор < сам по себе — это не выражение, а часть условного выражения.

Решение: используйте выражения с аргументом или без

Есть два основных подхода. Первый — передать в when аргумент и использовать in с диапазонами. Второй — использовать when без аргумента, где каждая ветка — это логическое условие.

Способ 1: Диапазоны с in

Самый простой способ для вашей задачи — использовать оператор in с диапазонами. Это работает для любых сравнимых типов:

val score = 85
when (score) {
    in Int.MIN_VALUE until 60 -> println("Неудовлетворительно")
    in 60..70 -> println("Удовлетворительно")
    in 71..85 -> println("Хорошо")
    in 86..Int.MAX_VALUE -> println("Отлично")
}

Но это громоздко. Kotlin позволяет использовать .. и until для открытых/закрытых диапазонов. Однако для строгих сравнений (<, >) удобнее второй способ.

Способ 2: when без аргумента (рекомендуется)

Если вы не передаёте аргумент в when, каждая ветка должна быть булевым выражением. Это идеально подходит для сравнений:

val score = 85
when {
    score < 60 -> println("Неудовлетворительно")
    score in 60..70 -> println("Удовлетворительно")
    score in 71..85 -> println("Хорошо")
    score > 85 -> println("Отлично")
}

Обратите внимание: score < 60 — это корректное булево выражение. Такой синтаксис работает и для любых других операторов: <=, >=, >, <.

Продвинутые примеры

Вы можете комбинировать условия с помощью && и ||:

val temperature = 25
when {
    temperature < 0 -> println("Мороз")
    temperature in 0..10 -> println("Холодно")
    temperature in 11..20 -> println("Прохладно")
    temperature in 21..30 -> println("Тепло")
    temperature > 30 -> println("Жарко")
}

Также можно использовать else для всех остальных случаев:

when {
    score < 60 -> println("Плохо")
    score < 75 -> println("Средне")
    score < 90 -> println("Хорошо")
    else -> println("Отлично")
}

Когда использовать какой способ?

  • С аргументом — когда проверяете конкретные значения (например, when (x) { 1 -> ... }) или диапазоны через in.
  • Без аргумента — когда нужно сложное условие с операторами сравнения, логическими операторами или когда условия независимы.

Оба подхода — идиоматичны для Kotlin. Выбирайте тот, который делает код понятнее.

<<>>

Альтернатива: использование функции сравнения

Если вам не нравится синтаксис when без аргумента, можно создать вспомогательную функцию-расширение для чисел, которая возвращает Comparable результат. Но это уже излишне для простых задач.

Более практичный вариант — использовать compareTo внутри when:

val score = 85
when (score.compareTo(60)) {
    -1 -> println("Неудовлетворительно")
    0, 1 -> when (score.compareTo(85)) {
        -1, 0 -> println("Хорошо")
        1 -> println("Отлично")
    }
}

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

Ещё один совет: если у вас много веток с диапазонами, рассмотрите использование when с in и константами для границ — это улучшит читаемость:

val FAIL = Int.MIN_VALUE until 60
val GOOD = 71..85

when (score) {
    in FAIL -> println("Неуд")
    in GOOD -> println("Хорошо")
    else -> println("Другое")
}

Главное правило: выбирайте подход, который делает код самодокументируемым. Kotlin даёт гибкость, но не злоупотребляйте ею.