Может ли контракт Kotlin подразумевать невозможность обнуления всех vararg-аргументов функции?
Я хотел бы написать функцию верхнего уровня следующим образом:
@ExperimentalContracts
fun containsNull(vararg objs: Any?): Boolean {
contract {
returns(false) implies (/* ???? */)
}
for (o in objs) if (o == null) return true
return false
}
так что я могу компилировать такой код без ошибок
if (containsNull(value1, value2, value3)) return
doSomething(value1.myProperty)
/* and similar calls multiple times, without the need to use the "?." operator */
но, кажется, нет возможности заполнить
Таким образом, единственный способ добиться этого - создать несколько функций, таких как:
containsNull(obj1: Any?, obj2: Any?)
containsNull(obj1: Any?, obj2: Any?, obj3: Any?)
etc...
и подразумевают невозможность обнуления для каждого отдельного аргумента в каждом отдельном контракте.
ИЛИ вместо того, чтобы писать функции, делать что-то вроде этого
try {
value1!!
value2!!
} catch (e: NullPointerException) {
return
}
doSomething(value1.myProperty)
который немного меньше загромождает, чем каскад
Я правильно угадываю? Есть ли более краткий и чистый способ обойти это?
1 ответ
На данный момент кажется, что невозможно достичь решения с помощью комбинацииvararg
и контракты, поэтому я остановился на подходе функций. В одном файле я поставил подписку на контракты вверху
@file:OptIn(ExperimentalContracts::class)
затем я объявил все функции. В качестве примера вот тот, который принимает 5 параметров
fun oneOrMoreIsNull(
obj1: Any?,
obj2: Any?,
obj3: Any?,
obj4: Any?,
obj5: Any?
): Boolean {
contract {
returns(false) implies (
obj1 != null &&
obj2 != null &&
obj3 != null &&
obj4 != null &&
obj5 != null
)
}
return obj1 == null || obj2 == null || obj3 == null ||
obj4 == null || obj5 == null
}
Затем я могу вызвать функцию, и умное приведение правильно обнаружит ненулевые значения.
if (oneOrMoreIsNull(arg1, arg2, arg3, arg4, arg5)) return
// All these examples now don't require null checking.
arg1.fancyComputation()
if (arg2.isValid()) doSomething()
doSomeMath(arg3.value, arg4.value)