Federico Bellini
Federico Bellini

Reputation: 514

Kotlin: Type mismatch: inferred type is Unit but Void was expected

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

Answers (1)

Tenfour04
Tenfour04

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

Related Questions