Today while programming I found some odd behaviour in Kotlin. I could easily go around it, but I wonder if there is some reason to it or if it is a bug in Kotlin.
I have the following interface of a delegate which delegates the showing of a dialog to the Activity.
interface ViewModelDelegate {
fun showWarningDialog(textResource: Int)
}
I want to implement it as following in the Activity. Since I know I can only do it with a context and the Activity.getContext()
may return null
, I wrap the code in context?.let
override fun showWarningDialog(textResource: Int) = context?.let {
//show dialog
}
However this gives me a compile error:
Return type of 'showWarningDialog' is not a subtype of the return type of the overridden member 'public abstract fun showWarningDialog(textResource: Int): Unit defined in com.some.class.path'
Which really confused me, because I don't want to return anything. So since let
returns whatever the function inside returns, I was wondering if I could fix it by writing a version of let which does not return anything.
fun <T, R> T.myLet(block: (T) -> R) {
let(block)
}
However this did not remove the compiler error. I found then that the mouseover text over the error gives more information (would be nice if the compiler did). It says:
Return type is 'Unit?', which is not a subtype of overridden
Now that tells me more about the problem. Because the function context?let
call may not happen, it could return null
. Now there are multiple ways to go around this. I could add ?: Unit
too the end of the function call or I could define showWarningDialog
to return Unit?
which will allow me to call it just fine in most cases. However none of these solutions are desireable. I will probably just make a normal method and call the let
inside of that instead of delegating the call to it. Costs me another level of indentation and an extra vertical line:
override fun showWarningDialog(textResource: Int) {
context?.let {
//show dialog
}
}
My question is, is this behaviour intended? Why or when would this be useful that a function that returns Unit cannot be delegated to an optional function call. I am very confused by this behaviour.
override fun showWarningDialog(textResource: Int) { context?.let { //show dialog } }
– Andrei Tanana