Условия и циклы: if, when, for, while
В Kotlin if и when — это выражения, которые возвращают значение, а циклы for удобно работают с диапазонами и коллекциями.
Суть: when заменяет громоздкий switch и цепочки if-else, а способность ветвлений возвращать значение делает код короче и выразительнее.
Главное отличие управляющих конструкций Kotlin от Java в том, что if и when — выражения. Они возвращают значение, поэтому ими можно прямо инициализировать переменную. Это убирает многословные конструкции, где сначала объявляли переменную, а потом присваивали её в ветках.
val age = 18
// if как выражение
val status = if (age >= 18) "взрослый" else "несовершеннолетний"
println(status) // взрослыйКонструкция when
when — это улучшенный switch. Он сопоставляет значение с вариантами, поддерживает диапазоны, несколько значений через запятую и проверку типов. И, как if, тоже возвращает значение.
fun describe(x: Int): String = when {
x < 0 -> "отрицательное"
x == 0 -> "ноль"
x in 1..9 -> "одна цифра"
else -> "большое число"
}
println(describe(-5)) // отрицательное
println(describe(0)) // ноль
println(describe(7)) // одна цифра
println(describe(99)) // большое числоЦиклы и диапазоны
Цикл for в Kotlin перебирает диапазоны и коллекции. Диапазон задаётся через .. (включая конец), until (исключая конец) или downTo (по убыванию). Шаг задаётся через step.
for (i in 1..5) print(i) // 12345
println()
for (i in 0 until 5) print(i) // 01234 (5 не входит)
println()
for (i in 10 downTo 1 step 2) print("$i ") // 10 8 6 4 2
println()
val fruits = listOf("яблоко", "груша", "слива")
for (f in fruits) println(f)Как работает под капотом
Диапазон 1..5 — это объект IntRange, реализующий интерфейс перебора. Поэтому for по нему работает так же, как по списку. Конструкция when компилируется в эффективную таблицу переходов или в цепочку проверок в зависимости от условий. Когда when используется как выражение, компилятор требует покрыть все случаи (например, ветку else), иначе результат был бы неопределён.
when (как выражение)
значение --> [ветка 1] --> результат
--> [ветка 2] --> результат
--> [else] --> результат
Все ветки обязаны вернуть значение совместимого типаЧастые ошибки
Забывать else в when-выражении. Если when возвращает значение, компилятор требует исчерпывающего покрытия. Для enum и sealed-классов он умеет проверять полноту без else.
Путать .. и until. 1..5 включает 5, а 1 until 5 — нет. На индексах массива это частый источник ошибки на единицу.
Писать цепочки if-else там, где просится when. Длинные лестницы условий читаются хуже компактного when.
Best practices
- Используйте
ifиwhenкак выражения, инициализируя ими переменные напрямую. - Три и более ветвей — повод заменить if-else на
when. - Для перебора индексов берите
indicesилиwithIndex(), а не ручной счётчик. - Помните разницу
..иuntil, чтобы не выйти за границы.
Логику when удобно прорепетировать на Python — классификация числа по веткам. Запустите врезку.
# Аналог when-выражения из Kotlin
def describe(x):
if x < 0: return 'отрицательное'
if x == 0: return 'ноль'
if 1 <= x <= 9: return 'одна цифра'
return 'большое число'
for v in [-5, 0, 7, 99]:
print(v, '->', describe(v))Попробуй сам ▶ — добавьте ветку для отрицательных однозначных чисел или для диапазона 10..99. В Kotlin это была бы новая строка в when.
Закрепим главное
Удержите в голове связку «выражение вместо инструкции»: в Kotlin ветвление не просто выбирает путь исполнения, а вычисляет значение. Это смещает стиль мышления — вместо «объяви переменную, потом в каждой ветке присвой её» вы пишете «переменная равна результату when». Меньше промежуточных состояний — меньше места для ошибки. Тот же подход вы встретите в Compose, где функция-экран по сути вычисляет описание UI из состояния через ветвления.
Второй ориентир — читаемость диапазонов. Диапазоны делают намерение явным: for (i in list.indices) честно говорит «перебираю индексы», а for ((index, value) in list.withIndex()) сразу даёт и позицию, и элемент. Эти идиомы вытесняют ручные счётчики и снимают целый класс ошибок выхода за границы. Привыкайте читать цикл как описание намерения, а не как механику инкремента.
Итог: ветвления-выражения и мощный when делают код короче и понятнее, а диапазоны превращают циклы в декларативные конструкции. Эти инструменты вы будете встречать в каждом экране Android-приложения.