lazy と lateinit
CoddyのKotlinジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 10/57。
by lazy { ... } は、val の計算を最初に読み取るまで遅延させ、その後結果を記憶します。計算コストが高い値や、常に必要とは限らない値に適しています。
class Report(val rows: List<Int>) {
val summary: String by lazy {
println("computing summary")
"total ${rows.sum()}"
}
}main の中では次のようにします。
val r = Report(listOf(3, 4))
println("created")
println(r.summary)
println(r.summary)出力:
created
computing summary
total 7
total 7ブロックは一度だけ実行されます。上記の 2 回目の読み取りでは、保存された結果が使用されました。すべての読み取りで実行されるカスタム getter とは異なり、lazy は一度だけ計算してキャッシュします。
class Demo {
var reads = 0
val viaGetter: Int
get() { reads++; return 42 }
val viaLazy: Int by lazy { reads++; 42 }
}main の中で:
val d = Demo()
repeat(3) { d.viaGetter; d.viaLazy }
println(d.reads)出力:
4lateinit var は、構築後、たとえばセットアップメソッドによって後から代入される非 null プロパティを宣言します。代入される前に読み取ると例外が発生し、::name.isInitialized で初期化済みかどうかを確認できます。
class Screen {
lateinit var title: String
fun load(t: String) { title = t }
fun ready() = ::title.isInitialized
}main の中では次のようにします。
val s = Screen()
println(s.ready())
s.load("Home")
println(s.ready())
println(s.title)出力:
false
true
Home構築時に値がわかっている場合は、通常の初期化を優先してください。不要になる可能性がある、コストの高いvalにはlazyを使用し、値が本当に後から設定されるvarにのみlateinitを使用してください。lateinitはInt、Boolean、その他のプリミティブ型では機能しません。
val config by lazy { loadConfig() } // 初回使用時に一度だけ計算される
lateinit var user: User // 構築後に代入される
// lateinit var count: Int // error: プリミティブ型では許可されていませんチャレンジ
簡単Document(val text: String) クラスを完成させてください。単一のスペースで区切られた単語数を数え、計算するたびに computations に 1 を加えて記録する lazy プロパティとして wordCount を追加し、作成者が設定されていない場合は by Ada または by unknown を返すメソッド credit() を持つ lateinit var author: String も追加してください。
提供されているコードはテキストを読み取り、wordCount を 3 回読み取り、2 行目が存在する場合は作成者を設定し、words 5, computed 1, by Ada を出力します。
コードは Document.kt に記述してください。Main.kt には提供された入力/出力コードが含まれており、編集できません。
自分で試してみよう
fun main() {
// 提供された入力/出力コード: そのままにしておく
val input = generateSequence(::readLine).toList()
val doc = Document(input[0])
val reads = List(3) { doc.wordCount }
val words = reads.first()
if (input.size > 1) doc.author = input[1]
println("words $words, computed ${doc.computations}, ${doc.credit()}")
}
このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。
オブジェクト指向プログラミングのすべてのレッスン
自分で練習してみよう: Kotlinプレイグラウンド