На этом шаге мы рассмотрим синтаксис и логику использования этой конструкции.
Условное выражение when - еще один способ управления потоком выполнения в Kotlin. Как и if/else, оператор when позволяет писать условия и выполнять код, соответствующий истинному условию. when обеспечивает краткий синтаксис и особенно хорошо подходит для условий с тремя и более ветвями.
Предположим, что в NyetHack игрок может быть представителем одной из выдуманных рас (race), например орком или гномом, а эти расы, в свою очередь, представляют разные фракции (faction). Оператор when берет выбранную расу и возвращает соответствующую фракцию:
val race = "gnome" // Раса val faction = when (race) { "dwarf" -> "Keepers of the Mines" "gnome" -> "Keepers of the Mines" "orc" -> "Free People of the Rolling Hills" "human" -> "Free People of the Rolling Hills" }
Рис.1. Пример использования when
Для начала объявим val race. Затем следующую переменную - faction, которой присвоим результат условного выражения when. Выражение проверяет значение race на соответствие каждому значению слева от оператора -> (стрелка) и, если находит соответствующее значение, присваивает faction значение справа (-> часто используется во многих языках и фактически имеет и другие сферы применения в Kotlin, о чем мы поговорим далее).
По умолчанию условное выражение when действует подобно оператору сравнения == между аргументом, который вы указали в скобках, и значением, указанным в фигурных скобках. (Аргумент - это входные данные для участка кода.)
В этом примере условного выражения when race служит аргументом, поэтому компилятор сравнит race, которое в примере имеет значение "gnome", с первым условием. Они не равны, поэтому компилятор переходит к следующему условию. Следующее сравнение вернет истинный результат, поэтому значение faction получит значение "Keepers of the Mines".
// Раса val faction = when (race) { "dwarf" -> "Keepers of the Mines" "gnome" -> "Keepers of the Mines" "orc" -> "Free People of the Rolling Hills" "human" -> "Free People of the Rolling Hills" else -> "" }
Теперь, когда вы увидели преимущества условного выражения when, удалите логику вычисления healthStatus. В отличие от прежде использовавшегося оператора if/else, оператор when делает код более простым и компактным. На практике применяется простое эмпирическое правило: используйте оператор when, если if/else содержит ветви else if.
Обновите логику healthStatus, используя when.
val healthStatus = when (healthPoints) { 100 -> "is in excellent condition!" in 90..99 -> "has a few scratches." in 75..89 -> if (isBlessed) { "has some minor wounds but is healing quite quickly!" } else { "has some minor wounds." } in 15..74 -> "looks pretty hurt." else -> "is in awful condition!" }
Рис.2. Рефакторинг кода healthStatus с оператором when (Game.kt)
Условное выражение when работает так же, как условное выражение if/else, определяя условия и выполняя ветви, где эти условия истинны. when отличается тем, что автоматически выбирает условие слева, соответствующее значению аргумента в области видимости. Подробнее мы поговорим про область видимости чуть позже. Рассмотрим кратко условное выражение in 90..99.
Вы уже видели, как использовать ключевое слово in для проверки принадлежности значения интервалу, и то же происходит здесь: проверяем значение healthPoints, хотя и не упоминаем об этом явно. В области видимости интервала, слева от ->, находится переменная healthPoints, поэтому компилятор вычислит оператор when, как если бы healthPoints входила в каждое условие ветвления.
Часто when лучше передает логику кода. В этом случае, чтобы получить тот же результат с помощью оператора if/else, потребуется добавить три ветви else if. Оператор when делает это более простым способом.
Условное выражение when обеспечивает большую гибкость, чем оператор if/else, при сопоставлении с заданными условиями. Большинство условий слева вычисляются как истинные или ложные, другие ограничиваются простым сравнением, как в примере с условием 100. Условный оператор when может выразить любое из них, как показано в примере выше. Кстати, можно ли заменить вложенный оператор if/else в одной из ветвей условного выражения when? Такая конструкция встречается не часто, но гибкость when позволяет реализовать ее.
Запустите NyetHack, чтобы убедиться, что в результате рефакторинга healthStatus с использованием оператора when логика выполнения программы не изменилась.
На следующем шаге мы рассмотрим шаблонные строки.