为什么这个不可为空的val变得"可以为空"?

Use*_*291 2 lambda type-inference callback kotlin kotlin-null-safety

所以我有一个简单的回调类:

class Callback<T>(
    val onResponse: (T) -> Unit,
    val onError:(Throwable)->Unit
)
Run Code Online (Sandbox Code Playgroud)

现在我想实现一个处理错误的方法.可能会或可能不会callback需要调用.

private fun handleServerError(error:IServerError, callback:Callback<*>? = null){
    val reason = error.cause

    when(reason){
        is Because.ServerRejectsLogin -> {
            doAsync { uiThread { mainActivity.longToast("sorry, your session timed out. please log in again.") } }
            IntentManager.doLogin(mainActivity)
        }
        else -> callback?.onError(reason)
    }
}
Run Code Online (Sandbox Code Playgroud)

这给我一个错误:

Reference有一个可以为null的类型((Throwable) -> Unit)?使用explicit ?.invoke()来进行类似函数的调用

它似乎期待的是

else -> callback?.onError?.invoke(reason)
Run Code Online (Sandbox Code Playgroud)

而且我不太明白为什么.不应该callback是非空的事实足以导致必须有一个非空onError函数?

如果我写的话,加上侮辱伤害

else -> callback?.let{it.onError(reason)}
Run Code Online (Sandbox Code Playgroud)

然后它接受了但不是在警告我我应该之前

删除多余的.let电话

zsm*_*b13 5

callback?.onError()如果你调用一个调用的函数的语法是正确onError的对callback与安全调用操作的对象.但是,在这种情况下,您首先读取属性callback,然后调用属性返回的另一个函数.

所以不是只包含一步和两件的表达式:

callback   ?.onError()
Run Code Online (Sandbox Code Playgroud)

你实际拥有的是三个部分的表达式,连续两个运算符:

callback   ?.onError   ()
Run Code Online (Sandbox Code Playgroud)

这里的最后一步()是调用返回invoke的对象的运算符onError:

callback   ?.onError   .invoke()
Run Code Online (Sandbox Code Playgroud)

但是,由于onError使用安全调用操作符读取属性,因此该对象可能是null.在这种情况下,您不能invoke以其运算符形式使用(顺便说一下,对于任何其他运算符也是如此),因此您必须明确地将其写出来,并添加另一个安全调用:

callback   ?.onError   ?.invoke()
Run Code Online (Sandbox Code Playgroud)

至于告诉您可以删除多余的意图操作let:这是一个错误,应该在问题跟踪器上报告.