【问题标题】:Why does this non-nullable val become "nullable"?为什么这个不可为空的 val 变成“可空的”?
【发布时间】:2019-07-15 17:29:24
【问题描述】:

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

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) -&gt; Unit)? 使用显式 ?.invoke() 进行类似函数的调用,而不是

似乎期待的是

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

我不太明白为什么。 callback 不为空这一事实是否足以推导出必须有一个非空的onError 函数?

雪上加霜,如果我写的话

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

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

删除多余的.let调用

【问题讨论】:

  • Shouldn't the fact that callback is not null be sufficient to derive that there must be a non-null onError function? 在您的情况下,您将callback 标记为可为空,因此它可能为空

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


【解决方案1】:

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

所以不是只包含一个步骤和两个部分的表达式:

callback   ?.onError()

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

callback   ?.onError   ()

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

callback   ?.onError   .invoke()

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

callback   ?.onError   ?.invoke()

至于意图动作告诉你可以删除多余的let:这是一个bug,应该在the issue tracker上报告。

【讨论】:

  • 嗯,这很有意义,实际上。谢谢你。您是否已经在跟踪器中提到了这一点,还是我应该继续添加它?
  • 我还没有为它创建问题,所以继续吧!也许也可以将其链接回此处。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-01-17
  • 2023-03-08
  • 2021-12-12
  • 1970-01-01
  • 2011-08-20
相关资源
最近更新 更多