I'm working on a multiplatform project and I'm trying to expose an API to add listeners:
interface InputEmitter {
fun addInputListener(listener: InputListener)
}
InputListener
is a SAM interface and it looks like this:
interface InputListener {
fun onInput(input: Input)
}
My problem is that this works properly from both Java and Kotlin but on the Kotlin side this is not idiomatic, since I have to invoke it like this:
obj.addInputListener(object : InputListener {
override fun onInput(input: Input) {
TODO("not implemented")
}
})
instead of this:
obj.addInputListener {
TODO("not implemented")
}
In this case the compiler complains about Type mismatch which is ok.
I could have solved this by using the @FunctionalInterface
annotation and in that case the Kotlin side would be better but since this is a multiplatform project I can't use that annotation.
Adding two functions:
fun addInputListener(listener: InputListener)
fun addInputListener(listener: (Input) -> Unit)
is not working either because it is ambiguous from the Java side. How can I solve this problem so that it works idiomatically from both Java and Kotlin?
I know that I can do something like this:
fun addInputListener(listener: InputListener)
fun onInput(listener: (Input) -> Unit)
but in that case the Java user will be puzzled when he/she wants to use the onInput
variant (because it resolves to Function1
which is not instantiable from the Java side).
Is there a canonical solution for this problem?