Kotlin – 安全呼叫运营商的链接。 不必要的话务员
以下面使用安全调用操作符(?。)的示例:
class Sample { class A( val sampleB: B? = B() ) class B( val sampleC: C = C() ) class C( val sampleInt: Int = 1 ) fun test() { val intInC: Int? = A().sampleB?.sampleC?.sampleInt } }
我知道我们需要一个安全的调用操作符sampleB。 但是为什么我们需要在sampleC上安全的调用操作符。 如果我删除该运算符,它不会编译。
基于我对运算符的理解,如果sampleB为空,则该行将返回null。 如果sampleB不为null,我们可以确定sampleC不是null,根据它的types。 但为什么Kotlin强制安全调用operatorC?
A().sampleB?.sampleC?.sampleInt
解析为
((A().sampleB)?.sampleC)?.sampleInt
types是
A(): A A().sampleB: B? (A().sampleB)?.sampleC: C? ((A().sampleB)?.sampleC)?.sampleInt: Int?
因为sampleC
之前的types是B?
, ?.
是必须的。
首先,安全呼叫运营商?.
不会打破安全通话链。 当你写A().sampleB?.sampleC?.sampleInt
,如果A().sampleB
为null,则链不会停在?.sampleC
但是它会执行null?.sampleC
。 A().sampleB?.sampleC
将是C?
但不是C
因为它取决于整个expression式而不是属性的types。 那是为什么?.
如果前面的expression式是可以为空的,则是需要的。
如果sampleB
是链中唯一可为空的expression式,则可以考虑使用.run
:
val intInC: Int? = A().sampleB?.run { sampleC.sampleInt }
我猜测你不相信,因为,正如你所说,如果它达到了链接点.sampleC
被称为是因为sampleB
不是空的,如果它是空的,它不会达到这一点。
这里的要点是,你正在考虑实施,从这个意义上说,你可能是对的。 但是,你需要从语义上解释它:尽管为了优化的原因,比方说,当它find一个null之前,它不需要走到最后,即使在那里,整条线也需要有连贯的含义是空的。 而为了这个事实,你需要?
符号。