Тернарный оператор в Kotlin: почему его нет и как не наступить на грабли
Если вы пришли в Kotlin из Java, C# или JavaScript, то наверняка хотя бы раз ловили себя на мысли: «Где же мой любимый тернарный оператор условие ? значение1 : значение2?». Спойлер: в Kotlin его нет. И это не баг, а фича. Разработчики языка решили, что классический тернарник — это лишняя сущность, которая только усложняет чтение кода, особенно когда вложенных условий становится больше двух.
Но отсутствие тернарного оператора — не проблема. Kotlin предлагает гораздо более гибкие и безопасные альтернативы. Однако новички (да и опытные разработчики) часто совершают одни и те же ошибки, пытаясь эмулировать привычную конструкцию. В этой статье мы разберём топ-5 ошибок при работе с условными выражениями в Kotlin и покажем, как их избежать. Поехали!
Ошибка №1: Попытка вставить тернарный оператор «в лоб»
Самая распространённая ошибка — написать код в стиле Java:
// ❌ Ошибка: такого синтаксиса в Kotlin нет
val max = (a > b) ? a : b
Kotlin просто не скомпилирует такой код. Вы получите ошибку: Unresolved reference: ?. Многие разработчики впадают в ступор и начинают искать библиотеки или плагины, которые «добавляют» тернарный оператор. Не делайте этого!
Как правильно?
В Kotlin if — это не оператор, а выражение. Оно возвращает значение. Поэтому вместо тернарника используйте обычный if-else:
// ✅ Правильный способ: if как выражение
val max = if (a > b) a else b
Код читается даже легче, чем классический тернарник, особенно если условие сложное. Запомните: if в Kotlin всегда возвращает последнее значение в каждой ветке.
Ошибка №2: Забыть про else при присваивании
Поскольку if — это выражение, оно обязано возвращать значение. Если вы напишете:
// ❌ Ошибка: нет else, компилятор не знает, что возвращать
val result = if (condition) "Yes"
Компилятор выдаст ошибку: All branches of 'if' expression are required to return a value. Это логично: что должно быть в result, если условие ложно? null? Пустая строка? Компилятор не угадывает.
Как правильно?
Всегда добавляйте else:
// ✅ Правильно: обе ветки возвращают значение
val result = if (condition) "Yes" else "No"
Исключение — если вы используете if как оператор (без присваивания). Тогда else не обязателен:
// Операторный if — else не нужен
if (condition) {
println("Yes")
}
Ошибка №3: Сложные вложенные if-else вместо when
Когда у вас больше двух вариантов, цепочка if-else if-else превращается в «спагетти». Посмотрите на этот ужас:
// ❌ Плохо: вложенные if-else тяжело читать
val status = if (code == 200) "OK"
else if (code == 404) "Not Found"
else if (code == 500) "Server Error"
else "Unknown"
Строчки прыгают, глаза разбегаются. А если добавить ещё пару условий — будет кошмар.
Как правильно?
Используйте when — это аналог switch на стероидах:
// ✅ Отлично: when читается как таблица
val status = when (code) {
200 -> "OK"
404 -> "Not Found"
500 -> "Server Error"
else -> "Unknown"
}
when в Kotlin тоже является выражением, поэтому может возвращать значение. И он гораздо нагляднее цепочки if-else. Кроме того, when поддерживает сложные условия: диапазоны, типы, произвольные выражения.
// when с диапазоном
val grade = when (score) {
in 90..100 -> "A"
in 80..89 -> "B"
in 70..79 -> "C"
else -> "D"
}
Ошибка №4: Игнорирование Elvis-оператора ?: для null-проверок
Новички часто пытаются написать что-то вроде:
// ❌ Плохо: избыточный if для null
val name = if (user != null) user.name else "Guest"
Это работает, но Kotlin предлагает более элегантное решение — Elvis-оператор (?:). Он похож на тернарный, но только для работы с nullable-значениями.
Как правильно?
// ✅ Элегантно: Elvis-оператор
val name = user?.name ?: "Guest"
Разберём по косточкам:
user?.name— безопасный вызов: еслиuser == null, то результатnull, иначе —user.name.?: "Guest"— если левая частьnull, используем "Guest".
Это кратко, безопасно и читаемо. Запомните: Elvis-оператор — это ваш лучший друг в мире null safety.
Но не путайте его с тернарным! ?: работает только с nullable-значениями, а не с произвольными булевыми условиями. Если вам нужно проверить не на null, а на что-то другое — используйте if-else или when.
Ошибка №5: Использование let и run там, где нужен простой if
Некоторые разработчики, насмотревшись на функциональный стиль, пытаются заменить простой if на цепочки let, also или run. Например:
// ❌ Плохо: избыточная функциональщина
val displayText = someValue?.let {
if (it > 0) "Positive" else "Non-positive"
} ?: "Null value"
Это работает, но читается тяжело. Зачем так усложнять, если можно написать проще?
Как правильно?
// ✅ Просто и ясно
val displayText = if (someValue != null) {
if (someValue > 0) "Positive" else "Non-positive"
} else {
"Null value"
}
Или ещё лучше — вынести логику в отдельную функцию:
Блоги
Рекомендаций по книгам
Читайте также
Монорепозиторий с Java: организация кода на практике
Code Review на PHP: 8 главных вещей, которые должен проверять каждый разработчик
std::wstring vs std::string: что выбрать для Unicode?
Безопасность JavaScript приложений: топ-10 уязвимостей для начинающих
Generics в PHP: зачем нужны и как использовать для начинающих