I have a function that looks something like:
fun MyInput?.toOutput() : Output? {
if (this == null) return null
return Output(this.someValue)
}
In places where I know that my MyInput
is non-null (for example, inside a method that takes a input: MyInput
as an arg), I'd like to be able to use input.toOutput
as Output
instead of Output?
I've tried using
contract {
returnsNotNull() implies (this@toOutput != null)
}
But that has the implication backwards. That tells me that if toOutput
returns a non-null type, that my input
was non-null. I want to tell the analyzer things about the return value based on the arguments. In Java, I could use org.jetbrains.annotations.@Contract("null -> null ; !null -> !null")
to accomplish this.
Is there a way to do this in Kotlin?
You don't need contracts for this. You just need to make a non-nullable overload. Like this:
fun MyInput?.toOutput(): Output? {
if (this == null) return null
return Output(this.someValue)
}
fun MyInput.toOutput(): Output = Output(this.someValue)
However, this will not work out of the box on the JVM, because the function signatures will clash. To make it work, you have to give one of the functions a new name with the @JvmName
annotation. For example:
@JvmName("toOutputNonNull")
fun MyInput.toOutput(): Output = Output(this.someValue)
You will still be able to call it like input.toOutput()
from Kotlin, but it will become something like FileNameKt.toOutputNonNull(input)
if you call it from Java.