Reputation: 514
How can I rewrite in Kotlin a (Throwable) -> Unit
into a (Throwable) -> Void
?
The thing I need to achieve is make the following code compile:
fun myKotlinMethod(onError: (Throwable) -> Unit) { // Can not change here
val onErrorJavaCompatible: (Throwable) -> Void = { t -> onError.invoke(t) } // Compilation error
MyJavaLibrary.aMethod(onErrorJavaCompatible) // Can not change here
}
Upvotes: 1
Views: 1564
Reputation: 93872
If you want to use a Kotlin function as a Java functional interface parameter, you need to convert it to that interface using SAM conversion, or you need to define an anonymous implementation of the interface (but that is verbose). Either way, Kotlin-Java interop will automatically switch between Unit/Void.
Assuming the interface in Java is named MyJavaCallback, here are two ways to do SAM conversion:
fun myKotlinMethod(onError: (Throwable) -> Unit) { // Can not change here
val onErrorJavaCompatible = MyJavaCallback { t -> onError(t) }
MyJavaLibrary.aMethod(onErrorJavaCompatible)
}
fun myKotlinMethod(onError: (Throwable) -> Unit) {
MyJavaLibrary.aMethod { t -> onError(t) }
}
Since you are directly passing through the code, you can prevent an unnecessary wrapper object around the Kotlin function by using inline
:
inline fun myKotlinMethod(crossinline onError: (Throwable) -> Unit) {
MyJavaLibrary.aMethod { t -> onError(t) }
}
One more step you can take for simpler code. When passing a function as a function, you don't need to put it in a lambda and invoke it:
inline fun myKotlinMethod(crossinline onError: (Throwable) -> Unit) {
MyJavaLibrary.aMethod(onError)
}
Just to be complete, here's how you would do it the verbose way, assuming the function in the Java interface is named onSomeEvent
:
inline fun myKotlinMethod(crossinline onError: (Throwable) -> Unit) {
val onErrorJavaCompatible = object: MyJavaCallback {
override fun onSomeEvent(t: Throwable) {
onError(t)
}
}
MyJavaLibrary.aMethod(onErrorJavaCompatible)
}
Upvotes: 2