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. Но зачем нам нужен оператор безопасного вызова на образце . Если я удалю этот оператор, он не скомпилируется.

Основываясь на моем понимании оператора, если sampleB был null, строка возвращает null. И если sampleB не является нулевым, мы можем быть уверены, что sampleC не является нулевым, в зависимости от его типа. Но почему Kotlin принуждает оператора безопасного вызова на образце C?

 A().sampleB?.sampleC?.sampleInt 

анализирует

 ((A().sampleB)?.sampleC)?.sampleInt 

Типы

 A(): A A().sampleB: B? (A().sampleB)?.sampleC: C? ((A().sampleB)?.sampleC)?.sampleInt: Int? 

Поскольку тип перед sampleC является B? , ?. необходимо.

Прежде всего, оператор безопасного вызова ?. не нарушит цепочку безопасных вызовов. Когда вы пишете A().sampleB?.sampleC?.sampleInt , если A().sampleB имеет значение null, цепочка не останавливается на ?.sampleC но она будет выполнять null?.sampleC . Тип A().sampleB?.sampleC будет C? но не C поскольку он зависит от всего выражения, но не от типа свойства. Вот почему ?. если предыдущее выражение является нулевым.

Если sampleB является единственным нулевым выражением в цепочке, вы можете использовать использование .run :

 val intInC: Int? = A().sampleB?.run { sampleC.sampleInt } 

Я предполагаю, что вы не уверены, потому что, как вы сказали, если он достигает точки в цепочке, где .sampleC называется, это потому, что sampleB не был нулевым, и если бы он был null, он бы не достиг этого.

Дело здесь в том, что вы думаете о реализации, и в этом смысле вы можете быть правы. Но вам нужно интерпретировать его семантически: хотя, по соображениям оптимизации, скажем, ему не нужно идти до конца строки, когда он находит нуль раньше, тем не менее, вся строка должна иметь согласованное значение, даже если является нулевым. И для того, чтобы быть правдой, вам нужно ? символ.