Контракт Kotlin выводит возвращаемое значение вместо значения аргумента

У меня есть функция, которая выглядит примерно так:

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

В местах, где я знаю, что мой MyInput не является нулевым (например, внутри метода, который принимает input: MyInput как аргумент), я хотел бы иметь возможность использовать input.toOutput как Output вместо Output?

Я пытался использовать

contract {
  returnsNotNull() implies (this@toOutput != null)
}

Но это имеет значение в обратном направлении. Это говорит мне, что если toOutput возвращает ненулевой тип, который мой input был ненулевым. Я хочу рассказать анализатору вещи о возвращаемом значении на основе аргументов. В Java я мог бы использовать org.jetbrains.annotations.@Contract("null -> null ; !null -> !null") чтобы достичь этого.

Есть ли способ сделать это в Котлине?

1 ответ

Решение

Вам не нужны контракты для этого. Вам просто нужно сделать ненулевую перегрузку. Как это:

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

fun MyInput.toOutput(): Output = Output(this.someValue)

Однако это не будет работать из коробки на JVM, потому что сигнатуры функций будут конфликтовать. Чтобы это работало, вы должны дать одной из функций новое имя с @JvmName аннотаций. Например:

@JvmName("toOutputNonNull")
fun MyInput.toOutput(): Output = Output(this.someValue)

Вы все еще сможете назвать это как input.toOutput() от Kotlin, но это станет чем-то вроде FileNameKt.toOutputNonNull(input) если вы звоните из Java.

Другие вопросы по тегам