JavaRush /Курсы /Kotlin SELF /if как выражение в Kotlin: присваиваем результат ветвлени...

if как выражение в Kotlin: присваиваем результат ветвления

Kotlin SELF
3 уровень , 5 лекция
Открыта

1. Введение

Если вы только что освоили if, то мозг пока воспринимает его как «перекрёсток»: если условие истинно — идём налево и что-то делаем, иначе — направо и тоже что-то делаем. И это нормально. Но в реальных программах нам часто нужно не только «сделать действие», а получить результат выбора: строку, число, метку, которую мы потом используем дальше.

Представьте, что вы выбираете, какую табличку повесить на дверь: "Открыто" или "Закрыто". Это не отдельное действие ради действия — это значение, которое нужно сохранить и потом вывести. Kotlin в этом месте говорит: «Окей, пусть if сразу возвращает табличку». И это очень удобно.

if как оператор и if как выражение

Когда мы пишем if «по-старому», он работает как оператор (statement): выполняет или не выполняет кусок кода, и на этом всё.

Но Kotlin разрешает использовать if как выражение (expression), то есть как штуку, у которой есть значение, как у 3 + 4 или у "Hi".length. Это официальная часть языка: if можно писать как выражение и присваивать его результат в переменную, но тогда ветка else становится обязательной.

Чтобы уловить идею, давайте сравним два стиля — «сначала завёл коробку (var), потом положил туда результат» и «сразу получил результат».

Вот стиль, который вы уже умеете (операторный if):

fun main() {
    val temperature = 28

    var label = "Нормально"
    if (temperature > 25) {
        label = "Жарко"
    }

    println(label) // Жарко
}

Здесь if ничего «не возвращает». Мы просто меняем label.

А вот стиль, который мы хотим освоить сегодня (выражение if):

fun main() {
    val temperature = 28

    val label = if (temperature > 25) "Жарко" else "Нормально"
    println(label) // Жарко
}

Разница по смыслу такая: во втором варианте мы прямо говорим Kotlin: «label — это результат выбора».

Базовый синтаксис: val x = if (cond) A else B

Базовая форма такая: val result = if (условие) значение1 else значение2. Она читается почти как человеческая фраза: «result равно (если условие, то значение1, иначе значение2)».


val result = if (condition) value1 else value2
Базовый синтаксис: if как выражение

Пример, который всегда хорошо заходит — модуль числа (абсолютное значение). В математике это |x|, а в коде мы просто выбираем: либо x, либо -x.

fun main() {
    val x = -7

    val abs = if (x >= 0) x else -x
    println("abs = $abs") // abs = 7
}

Обратите внимание: здесь мы вообще не используем var. Это маленькая, но важная победа: меньше изменяемых переменных — меньше мест, где можно «случайно всё сломать».

Почему else обязателен

С точки зрения новичка требование «почему я не могу написать val r = if (cond) 1?» кажется придиркой. Но компилятор не вредничает, он заботится о логике: если вы присваиваете результат, то результат должен существовать всегда, при любом исходе условия.

В Kotlin прямо сказано: если if используется как выражение, ветка else обязательна.

Плохой пример (так нельзя):

fun main() {
    val isVip = true
    val discount = if (isVip) 10 // Ошибка компиляции: нет else
}

Хороший пример (так правильно):

fun main() {
    val isVip = true

    val discount = if (isVip) 10 else 0
    println("discount = $discount") // discount = 10
}

В этом месте удобно запомнить правило: если if стоит справа от = и вы хотите сохранить результат, то else всегда обязателен.

Ветки-блоки { ... }: значение — это последнее выражение

Часто в ветке нужно сделать не одну вещь: например, распечатать пояснение и только потом вернуть значение. Kotlin разрешает, чтобы каждая ветка была блоком { ... }. Тогда результатом ветки становится последнее выражение в блоке.

Сделаем мини-пример: выбираем, кого считать «выше» — Алису или Боба, и при этом печатаем, кого выбрали (как будто мы ведём лог).

fun main() {
    val heightAlice = 160
    val heightBob = 175

    val taller = if (heightAlice > heightBob) {
        println("Выбрали Алису") // Выбрали Алису (если бы условие было true)
        heightAlice
    } else {
        println("Выбрали Боба")  // Выбрали Боба
        heightBob
    }

    println("taller = $taller") // taller = 175
}

Заметьте «фокус»: println(...) — это не значение для taller. Значение — это последняя строка ветки (heightAlice или heightBob). Это очень важная привычка: в конце ветки if-выражения должно стоять то, что вы хотите вернуть.

Маленькая схема, как это работает

flowchart TD
    A["if (условие)"] -->|true| B["ветка then { ... }"]
    A -->|false| C["ветка else { ... }"]
    B --> D["значение = последнее выражение ветки then"]
    C --> E["значение = последнее выражение ветки else"]
    D --> F["итог if-выражения"]
    E --> F

2. else if и линейный стиль кода

Иногда у нас не «два варианта», а «три-четыре». И хорошая новость: цепочка if / else if / else тоже может быть выражением. То есть мы можем присвоить результат сразу, без промежуточных var.

Пример: у нас есть число x, и мы хотим получить строку "positive", "negative" или "zero".

fun main() {
    val x = 0

    val sign = if (x > 0) {
        "positive"
    } else if (x < 0) {
        "negative"
    } else {
        "zero"
    }

    println(sign) // zero
}

Этот стиль особенно хорош тем, что у переменной sign сразу понятный смысл: «это метка знака числа».

Как if-выражение помогает делать код «линейным»

До if-выражений часто пишут так: «объявил переменную var, потом в разных ветках присваиваю». Это рабочий подход, но он постепенно приводит к тому, что переменная живёт слишком долго и меняется слишком много раз.

Сравним два подхода на жизненной задаче: если строка пустая — заменить её на "EMPTY", иначе оставить как есть (после trim()).

Подход с var:

fun main() {
    val raw = "   Kotlin   "
    val trimmed = raw.trim()

    var label = "EMPTY"
    if (trimmed.length != 0) {
        label = trimmed
    }

    println(label) // Kotlin
}

Подход с if-выражением:

fun main() {
    val raw = "   Kotlin   "
    val trimmed = raw.trim()

    val label = if (trimmed.length == 0) "EMPTY" else trimmed
    println(label) // Kotlin
}

Второй вариант читается быстрее: «label — это либо "EMPTY", либо trimmed». И главное: label теперь val, а значит «табличку на двери» нельзя случайно поменять посреди программы.

3. Практический пример: «Касса со скидкой»

Сейчас мы соберём небольшую консольную программу, которая выглядит как реальный сценарий: пользователь вводит сумму заказа, а мы рассчитываем скидку и печатаем итог. Это честный тренажёр, на котором видно, где if как выражение делает код проще.

Идея такая:

1) читаем сумму (как строку), чистим пробелы, пытаемся распарсить в число через toIntOrNull();
2) если не число — печатаем сообщение об ошибке;
3) если число — определяем процент скидки: если сумма >= 1000, то скидка 10%, иначе 0%;
4) формируем сообщение и печатаем.

Шаг 1. Выбираем процент скидки как значение

Начнём с самого важного для этой лекции — присваивания результата ветвления:

fun main() {
    val sum = 1200

    val discountPercent = if (sum >= 1000) 10 else 0
    println("discountPercent = $discountPercent") // discountPercent = 10
}

Здесь видно главное: discountPercent — это результат выбора, значит if-выражение идеально подходит.

Шаг 2. Сообщение тоже можно «вычислить»

Новички часто делают так: в каждой ветке if печатают почти одинаковый текст. Это работает, но быстро приводит к дублированию. Вместо этого мы можем вычислить строку message, а печать оставить одной строкой.

fun main() {
    val finalSum = 950
    val discountPercent = 0

    val message = if (discountPercent > 0) {
        "Скидка $discountPercent% применена. Итог: $finalSum"
    } else {
        "Скидки нет. Итог: $finalSum"
    }

    println(message) // Скидки нет. Итог: 950
}

Обратите внимание: мы используем блоки { ... }, но последняя строка — именно строка, а не println.

Шаг 3. Полная версия main

Ниже — цельный пример. Он чуть длиннее отдельных кусочков (потому что реальная программа всё-таки делает ввод/проверки), но все приёмы здесь уже знакомы.

fun main() {
    print("Введите сумму заказа: ")
    val sumText = readln().trim()
    val sum = sumText.toIntOrNull()

    if (sum == null) {
        println("Ошибка: нужно ввести целое число.") // Ошибка: нужно ввести целое число.
    } else {
        val discountPercent = if (sum >= 1000) 10 else 0
        val discount = sum * discountPercent / 100
        val finalSum = sum - discount

        val message = if (discountPercent > 0) {
            "Скидка $discountPercent% (-$discount). Итог: $finalSum"
        } else {
            "Скидки нет. Итог: $finalSum"
        }

        println(message) // пример: Скидка 10% (-120). Итог: 1080
    }
}

Здесь есть важный стиль мышления: мы стараемся делать переменные «одноразовыми фактами». discountPercent, discount, finalSum, message — это не «ящики, которые меняются», а «результаты вычислений». Когда вы привыкаете к этому, код становится предсказуемее: вы читаете его сверху вниз, как рецепт.

1
Задача
Kotlin SELF, 3 уровень, 5 лекция
Недоступна
Модуль долга
Модуль долга
1
Задача
Kotlin SELF, 3 уровень, 5 лекция
Недоступна
Табличка двери
Табличка двери
1
Задача
Kotlin SELF, 3 уровень, 5 лекция
Недоступна
Рейтинг игрока
Рейтинг игрока
1
Задача
Kotlin SELF, 3 уровень, 5 лекция
Недоступна
Ник без пробелов
Ник без пробелов
1
Опрос
Условные операторы и логика, 3 уровень, 5 лекция
Недоступен
Условные операторы и логика
Условные операторы и логика
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Александр Уровень 4
13 июня 2026
В задаче "Рейтинг игрока" ничего делать не надо, просто жмете "Проверка" и задача решена. Что несколько сбивает с толку. Задача "Модуль долга" сформулирована непонятно. В задаче требуется, чтобы если число отрицательное оно выводилось с минусом. Если ничего не делать, то оно и выведется с минусом, потому что оно отрицательное. Но это не является решением задачи...