Contracts в Kotlin — это способ сообщить компилятору о свойствах функции, которые нельзя выразить типами.
Обычно это:
- вызывается ли лямбда
- выполняется ли return
- можно ли сделать smart cast после проверки
Зачем нужны Kotlin Contracts?
- Улучшить smart cast’ы
- Гарантировать, что лямбда вызовется ровно один раз
- Упростить чтение кода и избавиться от warning-ов
- Повысить безопасность при использовании
check()
,require()
,assert()
,ifNull()
Пример 1: Smart cast без контракта
fun isString(obj: Any?): Boolean = obj is String
fun test(x: Any?) {
if (isString(x)) {
println(x.length) // Ошибка: x не smart cast-ится в String
}
}
Компилятор не знает, что isString(x)
==true
, то есть x
точно String
.
Пример 2: С контрактом
inline fun <T> Any?.isNotNullAndCast(): Boolean {
contract {
returns(true) implies (this@isNotNullAndCast is T)
}
return this is T
}
///....
if (x.isNotNullAndCast<String>()) {
println(x.length) // OK — smart cast работает
}