オブジェクト式
CoddyのKotlinジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 15/57。
オブジェクト式は、必要な場所で名前のないクラスの一度限りのオブジェクトを作成します。object : Type { ... }と記述し、通常はインターフェースを実装します。インターフェースには、どのように動作するかを示さずにメソッドを列挙します。インターフェースについては第5章で詳しく説明します。
interface Greeter {
fun greet(name: String): String
}mainの内部では次のようにします。
val polite = object : Greeter {
override fun greet(name: String) = "Good morning, $name."
}
println(polite.greet("Ada"))出力:
Good morning, Ada.オブジェクト宣言は一度だけ存在します。オブジェクト式は、そのコードが実行されるたびに評価され、実行ごとに新しいオブジェクトが作成されます。オブジェクト式は、その周囲にあるローカル変数を読み取ったり変更したりできます。
interface Counter {
fun next(): Int
}
fun counterFrom(start: Int): Counter {
var current = start
return object : Counter {
override fun next() = current++
}
}mainの内部では:
val a = counterFrom(10)
val b = counterFrom(1)
println("${a.next()} ${a.next()} ${b.next()}")出力:
10 11 1よくある用途の一つは、動作をライブラリ関数に渡すことです。sortedWithはComparatorを受け取ります。これは、メソッドcompare(a, b)が、aが先に来る場合は負の数、同順位の場合はゼロ、それ以外の場合は正の数を返すインターフェースです。
mainの内部:
val words = listOf("kiwi", "fig", "banana", "apple")
val byLength = object : Comparator<String> {
override fun compare(a: String, b: String) = a.length - b.length
}
println(words.sortedWith(byLength))出力:
[fig, kiwi, apple, banana]上位型を持たないオブジェクト式は、いくつかの値をローカルオブジェクトにまとめます。そのプロパティは同じ関数内で使用できます。インターフェースにメソッドが1つだけある場合は、オブジェクト式よりもラムダのほうが短くなることがよくあります。複数のメソッドがある場合や、保持しておく状態がある場合は、オブジェクト式が適しています。
val size = object {
val width = 3
val height = 4
}
println(size.width * size.height) // 12
val byLength = Comparator<String> { a, b -> a.length - b.length } // ラムダ形式チャレンジ
簡単インターフェース Validator には、テキストが条件を満たす場合はエラーメッセージまたは null を返すメソッド check(text) が1つあります。オブジェクト式で作成した3つのバリデーターを、次の順序で返すように関数 rules(minLength) を完成させてください。テキストは少なくとも minLength 文字(too short)であり、数字を含み(needs a digit)、スペースを含まない(no spaces allowed)必要があります。
提供されたコードは最小長を読み取り、その後に1行につき1つのパスワードを読み取ります。ok、またはそのパスワードのすべてのエラーメッセージを ; で結合したものを出力します。
コードは Rules.kt と Validator.kt に記述します。Main.kt には提供された入出力コードが含まれており、編集できません。
自分で試してみよう
fun main() {
// 提供された入出力コード: そのままにしておく
val input = generateSequence(::readLine).toList()
val checks = rules(input[0].toInt())
for (password in input.drop(1)) {
val problems = checks.mapNotNull { it.check(password) }
println(if (problems.isEmpty()) "ok" else problems.joinToString("; "))
}
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Kotlinプレイグラウンド