インターフェースを作成しました:
interface ProgressListener {
fun transferred(bytesUploaded: Long)
}
ただし、ラムダではなく匿名クラスとしてのみ使用できます
dataManager.createAndSubmitSendIt(title, message,
object : ProgressListener {
override fun transferred(bytesUploaded: Long) {
System.out.println(bytesUploaded.toString())
}
})
私はそれをラムダに置き換える可能性があると思う:
dataManager.createAndSubmitSendIt(title, message, {System.out.println(it.toString())})
しかし、エラーが発生しています:型の不一致。必須-ProgressListener、見つかった-()-> Unit?
何が間違っていますか?
@ zsmb13が言ったように、SAM変換はJavaインターフェイスでのみサポートされています。
ただし、機能する拡張機能を作成することもできます。
// Assuming the type of dataManager is DataManager.
fun DataManager.createAndSubmitSendIt(title: String,
message: String,
progressListener: (Long) -> Unit) {
createAndSubmitSendIt(title, message,
object : ProgressListener {
override fun transferred(bytesUploaded: Long) {
progressListener(bytesUploaded)
}
})
}
Kotlinは、JavaインターフェイスのSAM変換のみをサポートします。
...この機能はJava interopに対してのみ機能します。Kotlinには適切な関数タイプがあるため、Kotlinインターフェイスの実装への関数の自動変換は不要であり、サポートされていません。
- 公式ドキュメント
パラメーターでラムダを使用する場合は、関数がインターフェイスではなく関数パラメーターを取るようにします。 (少なくとも今のところ。KotlinインターフェースのSAM変換のサポートは継続的な議論であり、Kotlin 1.1ライブストリームで将来可能な機能の1つでした。)
少し遅れて:インターフェイスを作成する代わりに、次のように、データマネージャーのインターフェイスの代わりに関数を直接使用することで、コンパイルで作成できるようにします。
fun createAndSubmitSendIt(title: String, message: String, transferred: (Long) -> Unit) {
val answer = TODO("whatever you need to do")
transferred(answer)
}
そして、あなたはそれをあなたが望むように使うだけです!私の記憶が正しければ、kotlin/jvmコンパイラーが行うことは、インターフェースを作成することと同じです。
それが役に立てば幸い!
別の解決策は、typealiasを宣言し、どこかに挿入して呼び出すことです。ここに例:
internal typealias WhateverListener = (String) -> Unit
そして、そのタイプエイリアスをクラスに注入します:
class Gallery constructor(private val whateverListener: WhateverListener) {
...
galleryItemClickListener.invoke("hello")
...
}
ラムダがあります:
val gallery = Gallery { appNavigator.openVideoPlayer(it) }
同僚のジョエル・ペドラザに謝辞.