問題
JavaでInterface定義し、抽象メソッドが一つだけのもの(Single Abstract Method: SAM)をKotlinで呼び出すときは下記みたいな感じでいける
view.setOnClickListener { view ->
// something
}
一方、下記のようにKotlinでSAMのInterfaceを作っても同じように呼び出せない
- 呼ばれる側
interface HogeListener {
fun fuga(s: String)
}
setHogeListener(listener: HogeListener) {
this.listener = listener
}
- 呼ぶ側
hogehoge.setHogeListener { s ->
}
// ERROR:
// Type Mismatch.
// Required: A.HogeListener
// Found: (???) -> Unit
// Cannot infer a type for this parameter. Please specify it explicitly.
原因
Also note that this feature works only for Java interop; since Kotlin has proper function types, automatic conversion of functions into implementations of Kotlin interfaces is unnecessary and therefore unsupported.
JavaのSAMはよしなに変換してくれるけど、Kotlinは必要ないから変換しないとのこと。
対応
とりあえずJavaの時と使い勝手を変えたくなかったので下記のように実装。
class Hoge(private var listener: (String) -> Unit) {
fun fuga(string: String) {
listener(string)
}
}
setHogeListener(listener: (String)->Unit) {
listener = Hoge(listener)
}
実際にはKotlin化と同時に不要なインターフェースを無くしていくのがベストなんだろなぁと思いつつ、一時対応としてメモ。