为什么此不可为空的val变为“可为空”?

时间:2019-02-21 17:44:58

标签: lambda kotlin callback type-inference kotlin-null-safety

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

class Callback<T>(
    val onResponse: (T) -> Unit,
    val onError:(Throwable)->Unit
)

现在,我想实现一个处理错误的方法。可能有也可能没有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)
    }
}

这给我一个错误:

  

引用具有可为空的类型((Throwable) -> Unit)?,请使用显式?.invoke()进行类似函数的调用

似乎期望是

else -> callback?.onError?.invoke(reason)

我不太清楚为什么。 callback不为空这一事实是否足以推导必须存在非空的onError函数?

如果我写信要侮辱人

else -> callback?.let{it.onError(reason)}

然后它接受了,但是没有警告我应该

  

删除多余的.let通话

1 个答案:

答案 0 :(得分:5)

如果您正在使用安全调用运算符在callback?.onError()对象上调用名为onError的函数,那么callback语法将是正确的。但是,在这种情况下,您首先要读取callback的属性,然后根据该属性返回的内容调用另一个函数。

因此,表达式不是仅由一个步骤和两个部分组成:

callback   ?.onError()

您实际拥有的是一个由三部分组成的表达式,其中连续有两个运算符:

callback   ?.onError   ()

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

callback   ?.onError   .invoke()

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

callback   ?.onError   ?.invoke()

关于意图操作告诉您可以删除多余的let:这是一个错误,应在the issue tracker上进行报告。