親子関係のある独自のブロックを作りたい
親子関係のある独自のブロックを作りたい
Groovy風のType-Safe buildersを作りましょう。
関数を引数に渡すと出来そう
単純にブロックだけを作ろうとするとこういう関数を定義することになります。
fun parent(f: () -> Unit){}
fun child (f:() -> Unit){}
問題点
この関数には親子関係がないので、こう書けてしまいます。
parent{
println("おや")
}
child {
println("こども")
}
親子関係をType-Safe Buildersで表現
これも防ぎたい、あとうまく親子関係で情報を受け渡したい場合に Type-Safe Buildersです。
fun parent(init: Parent.() -> Unit) : Parent{
val parent = Parent()
parent.init()
return parent
}
class Parent(){
fun child(init: Child.() -> Unit) : Child {
val child = Child()
child.init()
return child
}
}
class Child
使い方
さっきのがコンパイルエラーになります
parent{
println("おや")
}
child { // コンパイルエラー!!
println("こども")
}
解説
Type-Safe Buildersのポイントはレシーバーです。
「クラス名().->」と書くことで、当該クラスをレシーバーとしてそのクラスインスタンスに従属する引数なしの関数という定義になります。
これを組み合わせると前述のようにクラスでうまく隠蔽や情報の伝達が可能になります。
最終更新日時:2016年5月29日