我有几个自定义范围函数,它们看起来都类似于这个:
@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(...) 具有相同的效果,但只有在满足条件时才会执行该块。该功能非常有效,但有一个警告。例如,如果条件包含空检查,则这些非空保证不会转换为被执行的块。
例如:
.applyIf(source != null) {
sourceClassName = source.className
sourceMethodName = source.methodName
})
上面会导致编译器警告,因为我使用的源代码没有 ?: 和 !! 运营商。IntelliJ 工具提示说
在 LogSource 类型的可空接收器上只允许安全 (?.) 或非空断言 (!!.) 调用?(源变量的类型为 LogSource)
获得与这种情况相同的行为的最佳方法是什么:
if(source != null) {
[...].apply {
sourceClassName = source.className
sourceMethodName = source.methodName
}
}
我想使用谓词或提供者而不是布尔值将是第一步,但是正确的合同语法是什么语法上说“如果条件包含空检查,则确认的非空值在块中和整个块中都是有效的除非改变”?