Menu
Coddy logo textTech

initブロックと検証

CoddyのKotlinジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 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 } は引数をチェックし、false の場合はメッセージとともに 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プレイグラウンド