Avatar ·

Использование Boolean? в условном выражении if в Kotlin

Всем привет! Я только начал изучать Kotlin после Java, и столкнулся с проблемой, которую не могу понять. У меня есть nullable переменная `isActive: Boolean?`, которая может быть `true`, `false` или `null`. Я хочу проверить её в условии `if`: ```kotlin var isActive: Boolean? = null if (isActive) { println("Активно") } else { println("Не активно") } ``` Но компилятор выдаёт ошибку: "Type mismatch: inferred type is Boolean? but Boolean was expected". Я понимаю, что `Boolean?` — это nullable тип, а `if` ожидает обычный `Boolean`. Но как правильно обработать такую ситуацию? Мне нужно, чтобы при `null` программа тоже что-то делала (например, считала, что это "не активно"). Подскажите, как это делается в Kotlin? Я пробовал использовать `if (isActive == true)`, но это кажется костылём. Есть ли более идиоматичный способ? Заранее спасибо за помощь! <<>>

Проблема: почему нельзя использовать Boolean? в if

В Kotlin тип Boolean? — это nullable-обёртка, которая может содержать три состояния: true, false и null. Условное выражение if в Kotlin строго типизировано и ожидает только Boolean (non-nullable). Это сделано для безопасности: если бы null автоматически интерпретировался как false, это могло бы привести к неожиданным ошибкам, как в Java с автоупаковкой.

Правильные способы обработки Boolean?

1. Явное сравнение с true (рекомендуемый способ)

Самый простой и читаемый подход — использовать if (isActive == true):

val isActive: Boolean? = null

if (isActive == true) {
    println("Активно")  // выполнится только если isActive == true
} else {
    println("Не активно")  // выполнится если false или null
}

Это не костыль, а идиоматичный способ. Код явно показывает, что мы рассматриваем null как "не активно".

2. Использование оператора ?: (Элвис)

Можно привести Boolean? к обычному Boolean со значением по умолчанию:

val isActive: Boolean? = null

if (isActive ?: false) {
    println("Активно")
} else {
    println("Не активно")
}

Оператор ?: возвращает правую часть, если левая равна null. Здесь null превращается в false.

3. Использование when для трёх состояний

Если вам нужно различать все три состояния (true, false, null):

val isActive: Boolean? = null

when (isActive) {
    true -> println("Активно")
    false -> println("Не активно")
    null -> println("Неизвестно")
}

Этот подход даёт максимальную гибкость, когда null имеет особый смысл (например, "статус не установлен").

4. Использование безопасного вызова с let

val isActive: Boolean? = null

isActive?.let { value ->
    if (value) {
        println("Активно")
    } else {
        println("Не активно")
    }
} ?: run {
    println("isActive == null")
}

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

Рекомендация

  • Для простой проверки на true с обработкой null как false — используйте if (isActive == true). Это наиболее читаемо.
  • Если null должен иметь отдельную логику — используйте when.
  • Избегайте if (isActive ?: false) в сложных выражениях — это может снизить читаемость.

Главное помнить: Kotlin заставляет вас явно обрабатывать null, что предотвращает множество багов, типичных для Java.

<<>>

Альтернативный подход: расширение для Boolean?

Если вам часто приходится работать с Boolean? и вы хотите сделать код ещё более выразительным, можно написать простое расширение:

fun Boolean?.orFalse(): Boolean = this ?: false

// Использование:
val isActive: Boolean? = null
if (isActive.orFalse()) {
    println("Активно")
} else {
    println("Не активно")
}

Или для явного сравнения с true:

fun Boolean?.isTrue(): Boolean = this == true

// Использование:
if (isActive.isTrue()) {
    println("Активно")
}

Это особенно удобно, когда Boolean? приходит из внешних источников (база данных, JSON, API). Однако не злоупотребляйте этим — для разовых проверок лучше использовать встроенные средства.

Также помните, что в Kotlin есть аннотация @RecentlyNonNull и @Nullable для совместимости с Java, но в чистом Kotlin-коде расширения — это отличный способ сделать nullable-логику более читаемой.