首页 > 解决方案 > 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(...) 具有相同的效果,但只有在满足条件时才会执行该块。该功能非常有效,但有一个警告。例如,如果条件包含空检查,则这些非空保证不会转换为被执行的块。

例如:

.applyIf(source != null) {
  sourceClassName = source.className
  sourceMethodName = source.methodName
})

上面会导致编译器警告,因为我使用的源代码没有 ?: 和 !! 运营商。IntelliJ 工具提示说

在 LogSource 类型的可空接收器上只允许安全 (?.) 或非空断言 (!!.) 调用?(源变量的类型为 LogSource)

获得与这种情况相同的行为的最佳方法是什么:

if(source != null) { 
  [...].apply {
    sourceClassName = source.className
    sourceMethodName = source.methodName
  }
}

我想使用谓词或提供者而不是布尔值将是第一步,但是正确的合同语法是什么语法上说“如果条件包含空检查,则确认的非空值在块中和整个块中都是有效的除非改变”?

标签: kotlinnull-checkkotlin-contracts

解决方案


推荐阅读