Как работает контракт компилятора с нулевой проверкой Kotlin?
У меня есть пара настраиваемых функций области видимости, которые все похожи на эту:
@OptIn(ExperimentalContracts::class)
inline fun <R> R.applyIf(condition: Boolean, block: R.() -> Unit): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
if(condition) block()
return this
}
Он имеет тот же эффект, что и apply(...), но блок выполняется только в том случае, если выполняется условие. Функция работает прекрасно, но есть один нюанс. Если условие содержит, например, проверки на null, эти ненулевые гарантии не переводятся в блок, который выполняется.
Так например:
.applyIf(source != null) {
sourceClassName = source.className
sourceMethodName = source.methodName
})
Вышеупомянутое приводит к предупреждению компилятора, потому что я использую исходный код без?: И !! операторы. Всплывающая подсказка IntelliJ говорит
Только безопасные (?.) Или ненулевые утвержденные (!!.) Вызовы разрешены для обнуляемого получателя типа LogSource?(исходная переменная имеет тип LogSource)
Как лучше всего добиться того же поведения, что и в этом случае:
if(source != null) {
[...].apply {
sourceClassName = source.className
sourceMethodName = source.methodName
}
}
Я полагаю, что использование предиката или поставщика вместо логического было бы первым шагом, но каков правильный синтаксис контракта, чтобы синтаксически сказать: «если условие содержит проверки на null, подтвержденные ненулевые значения действительны в блоке и во всем блоке. разве изменено "?