Saya telah menciptakan sebuah antarmuka:
interface ProgressListener {
fun transferred(bytesUploaded: Long)
}
tapi bisa menggunakannya hanya sebagai anonim kelas, tidak lambda
dataManager.createAndSubmitSendIt(title, message,
object : ProgressListener {
override fun transferred(bytesUploaded: Long) {
System.out.println(bytesUploaded.toString())
}
})
Saya pikir itu harus menjadi kemungkinan untuk menggantinya dengan lambda:
dataManager.createAndSubmitSendIt(title, message, {System.out.println(it.toString())})
Tapi saya mendapatkan error: Type mismatch; diperlukan - ProgressListener, ditemukan - () -> Unit?
Apa yang saya lakukan salah?
Seperti @zsmb13 mengatakan, SAM konversi hanya didukung untuk Java interface.
Anda dapat membuat perpanjangan fungsi untuk membuatnya bekerja meskipun:
// 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 hanya mendukung SAM konversi untuk Java interface.
... perhatikan bahwa fitur ini hanya bekerja untuk Jawa interop; sejak Kotlin memiliki fungsi yang tepat jenis, konversi otomatis dari fungsi ke implementasi Kotlin antarmuka yang tidak perlu dan karena itu tidak didukung.
Jika anda ingin menggunakan lambda dalam parameter, membuat fungsi anda mengambil sebuah parameter fungsi alih dari suatu interface. (Setidaknya untuk saat ini. Pendukung SAM konversi untuk Kotlin interface adalah sebuah diskusi yang sedang berlangsung, itu adalah salah satu fitur masa depan di Kotlin 1.1 live streaming.)
Sedikit terlambat ke pesta: alih-alih membuat sebuah antarmuka, anda membiarkan kompilasi membuat satu dengan mengambil fungsi ini diatas bukan sebuah antarmuka di datamanager, seperti ini:
fun createAndSubmitSendIt(title: String, message: String, transferred: (Long) -> Unit) {
val answer = TODO("whatever you need to do")
transferred(answer)
}
dan kemudian anda hanya menggunakannya seperti yang anda inginkan! Jika aku ingat benar, apa kotlin/jvm yang penyusun lakukan adalah sama seperti membuat sebuah antarmuka.
Semoga membantu!
Solusi lain akan dengan menyatakan typealias, penyuntikan di suatu tempat dan memohon itu. Berikut contoh:
internal typealias WhateverListener = (String) -> Unit
dan kemudian kita inject yang typealias ke kelas kami:
class Gallery constructor(private val whateverListener: WhateverListener) {
...
galleryItemClickListener.invoke("hello")
...
}
jadi kami memiliki lambda:
val gallery = Gallery { appNavigator.openVideoPlayer(it) }
Kredit untuk rekan saya Joel Pedraza, yang menunjukkan trik ketika mencoba untuk menemukan solusi <3.
Tidak ada satu solusi utama untuk masalah ini jika anda bertujuan akses terbaik dari kedua Kotlin dan Jawa.
Jika Kotlin pengembang tidak memikirkan SAM konversi untuk Kotlin antarmuka yang tidak perlu, "Kotlin Antarmuka" metode akan menjadi solusi utama.
https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions Juga dicatat bahwa fitur ini hanya bekerja untuk Jawa interop; sejak Kotlin memiliki fungsi yang tepat jenis, konversi otomatis dari fungsi ke implementasi Kotlin antarmuka yang tidak perlu dan karena itu tidak didukung.
Pilih solusi yang terbaik untuk kasus anda.
- Kotlin API: Sempurna
- Kotlin Akses: Sempurna
- Jawa Akses:
- Auto generated jenis parameter seperti Function1 (bukan masalah besar bagi Jawa 8 lambda)
- Verbose
kembali Unit.CONTOH;
bukannya batal kembali.
kelas KotlinApi { menyenangkan demo(pendengar: (respon: String) -> Unit) { pendengar("respon") } }
menyenangkan kotlinConsumer() { KotlinApi().demo { sukses -> println(sukses) } }
public void javaConsumer() { baru KotlinApi().demo(s -> { Sistem.keluar.println(s); kembali Unit.CONTOH; }); }
- Kotlin API: Tambahan interface definition.
- Kotlin Akses: Terlalu verbose
- Jawa Akses: Sempurna
kelas KotlinApi { antarmuka Pendengar { menyenangkan onResponse(respon: String) }
menyenangkan demo(pendengar: Pendengar) { pendengar.onResponse("respon") } }
menyenangkan kotlinConsumer() { KotlinApi().demo(objek : KotlinApi.Pendengar { menimpa menyenangkan onResponse(respon: String) { println(respon) } }) }
//Jika Kotlin telah didukung SAM konversi untuk Kotlin interface. :( //fun kotlinConsumer() { // KotlinApi().demo { // println(itu) // } //}
public void javaConsumer() { baru KotlinApi().demo(s -> { Sistem.keluar.println(s); }); }
- Kotlin API: Campur kode Java.
- Kotlin Akses: sedikit verbose
- Jawa Akses: Sempurna
kelas KotlinApi { menyenangkan demo(pendengar: Pendengar) { pendengar.onResponse("respon") } }
antarmuka publik Pendengar { batal onResponse(String response); }
//Semi SAM konversi menyenangkan kotlinConsumer() { KotlinApi().demo(Pendengar { println(itu) }) }
public void javaConsumer() { baru KotlinApi().demo(s -> { Sistem.keluar.println(s); }); }
- Kotlin API: Beberapa metode implementasi
- Kotlin Akses: Sempurna jika benar metode yang digunakan. Penyelesaian otomatis menunjukkan verbose metode juga.
- Jawa Akses: Sempurna. Penyelesaian otomatis tidak menunjukkan fungsi jenis metode karena
JvmSynthetic
penjelasan
kelas KotlinApi { antarmuka Pendengar { menyenangkan onResponse(respon: String) }
menyenangkan demo(pendengar: Pendengar) { demo { pendengar.onResponse(itu) } }
@JvmSynthetic //Mencegah JVM untuk menggunakan metode ini menyenangkan demo(pendengar: (String) -> Unit) { pendengar("respon") } }
menyenangkan kotlinConsumer() { KotlinApi().demo { println(itu) } }
public void javaConsumer() { baru KotlinApi().demo(s -> { Sistem.keluar.println(s); }); }
- Kotlin API: tidak Ada Kotlin API, semua kode API Jawa
- Kotlin akses: Sempurna
- Jawa akses: Sempurna
public class JavaApi { publik batal demo(Pendengar pendengar) { pendengar.onResponse("respon"); }
antarmuka publik Pendengar { batal onResponse(String response); }
}
//Full SAM konversi menyenangkan kotlinConsumer() { JavaApi().demo { println(itu) } }
public void javaConsumer() { baru JavaApi().demo(s -> { Sistem.keluar.println(s); }); }