Menu
Coddy logo textTech

Блоки init и валидация

Часть раздела Объектно-ориентированное программирование путешествия по Kotlin на Coddy. Урок 4 из 57.

Блок init выполняется при создании экземпляра сразу после присваивания параметров конструктора. Он предназначен для кода настройки, который не помещается в одно объявление свойства:

class Order(val id: Int, items: List<Int>) {
    val total: Int
    val count: Int

    init {
        total = items.sum()
        count = items.size
        println("created order $id")
    }
}

Внутри main:

val o = Order(7, listOf(4, 6, 10))
println("${o.count} items, total ${o.total}")

Вывод:

created order 7
3 items, total 20

require(condition) { message } проверяет аргумент и выбрасывает IllegalArgumentException с сообщением, когда условие ложно. Размещение этого вызова в init означает, что недопустимый экземпляр никогда не может быть создан:

class Percentage(val value: Int) {
    init {
        require(value in 0..100) { "percentage must be 0-100, was $value" }
    }
}

Внутри main:

println(Percentage(42).value)
try {
    Percentage(150)
} catch (e: IllegalArgumentException) {
    println(e.message)
}

Вывод:

42
percentage must be 0-100, was 150

У класса может быть несколько блоков init; они выполняются по порядку вместе с инициализаторами свойств, сверху вниз:

class Demo(name: String) {
    val first = "first: $name".also { println(it) }

    init { println("init 1") }

    val second = "second".also { println(it) }

    init { println("init 2") }
}

Внутри main:

Demo("x")
println("done")

Вывод:

first: x
init 1
second
init 2
done

Проверка в init размещает правило рядом с данными. Код, получающий экземпляр, может доверять ему и не проверять его снова:

class Email(val address: String) {
    init {
        require("@" in address) { "not an email: $address" }
    }
}
fun send(to: Email) { /* нет необходимости снова проверять адрес */ }
challenge icon

Задание

Легко

Завершите класс Password. Его блок init с помощью require проверяет, что текст содержит как минимум 8 символов (сообщение too short) и содержит цифру (сообщение needs a digit), именно в таком порядке. Свойство strength вычисляется в init: strong, если текст также содержит заглавную букву, и ok в противном случае.

Предоставленный код создаёт объект Password для каждой входной строки и выводит strength или сообщение об ошибке.

Ваш код должен находиться в Password.kt. В Main.kt содержится предоставленный код ввода/вывода, и его нельзя редактировать.

Попробуйте сами

fun main() {
    // Предоставленный код ввода/вывода: оставьте его как есть
    val input = generateSequence(::readLine).toList()
    for (line in input) {
        try {
            println(Password(line).strength)
        } catch (e: IllegalArgumentException) {
            println(e.message)
        }
    }
}
quiz iconПроверьте себя

В этом уроке есть небольшой тест. Начните урок, чтобы ответить на вопросы и сохранить прогресс.

Все уроки раздела Объектно-ориентированное программирование

Потренируйтесь самостоятельно: Песочница Kotlin