メンバー拡張メソッドの宣言
Kotlinでは、拡張メソッドを定義することができる。
通常はトップレベルに配置するが、実は拡張メソッドをメンバーとして定義することもできる。
interface Monoid<M> {
val identity: M
fun compose(a: M, b: M)
// Extension method as a member!
fun List<M>.fold(): M = fold(identity, this@Monoid::compose)
}
そこそこKotlinを使っていたけど、この前初めて知った。
2つのレシーバー
拡張メソッドをメンバーとして定義すると、本来のインスタンスを指すthis
と、拡張メソッドのレシーバーを指すthis
の2つが存在することになる。これをDispatch receiver, Extension receiverと呼び分ける。
通常Extension receiverが優先的に呼び出されるが、Qualified this構文を使うことでDispatch receiverを明示的に指定することができる。
interface Monoid<M> {
val identity: M
fun compose(a: M, b: M)
fun List<M>.fold(): M =
this.fold( // List::fold
this.identity, // Monoid::identity
this@Monoid::compose // Monoid::compose
)
}
メンバー拡張メソッドの呼び出し
呼び出すときはwith
を使うのが便利だ。
object MonoidString : Monoid<String> {
override val identity: String = ""
override fun compose(a: String, b: String): String = a + b
}
fun main() {
with (MonoidString) {
println(listOf("Hello", " ", "World").fold())
}
}
ScalaのImplicit parametersみたいで面白い。