Kotlin合约推断返回值而不是参数值

kar*_*arl 3 kotlin kotlin-contracts

我有一个看起来像这样的函数:

fun MyInput?.toOutput() : Output? {
  if (this == null) return null
  return Output(this.someValue)
}
Run Code Online (Sandbox Code Playgroud)

在我知道我MyInput的非空值的地方(例如,在以a input: MyInput作为参数的方法内部),我希望能够使用input.toOutputas Output代替Output?

我试过使用

contract {
  returnsNotNull() implies (this@toOutput != null)
}
Run Code Online (Sandbox Code Playgroud)

但这意味着倒退。这告诉我,如果toOutput返回非空类型,则我input为非空。我想告诉分析器有关基于参数的返回值的信息。在Java中,我可以org.jetbrains.annotations.@Contract("null -> null ; !null -> !null")用来完成此任务。

Kotlin有办法做到这一点吗?

mar*_*ran 5

您不需要合同。您只需要进行一个不可为空的重载。像这样:

fun MyInput?.toOutput(): Output? {
  if (this == null) return null
  return Output(this.someValue)
}

fun MyInput.toOutput(): Output = Output(this.someValue)
Run Code Online (Sandbox Code Playgroud)

但是,这在JVM上不是开箱即用的,因为功能签名会发生冲突。为了使它起作用,您必须给其中一个函数加上新的@JvmName注释名称。例如:

@JvmName("toOutputNonNull")
fun MyInput.toOutput(): Output = Output(this.someValue)
Run Code Online (Sandbox Code Playgroud)

您仍然可以像input.toOutput()从Kotlin 一样调用它,但是FileNameKt.toOutputNonNull(input)如果您从Java调用它,则将变得像。