Это беспокоило меня пару часов, тем более что это возможно:
val x: Any = "string"
require(x is String)
val len = x.length
Компилятор явно способен понять это, так что это, вероятно, ограничение самих контрактов.
Я провел некоторое время, пытаясь найти обходные пути. Для справки:
@UseExperimental(ExperimentalContracts::class)
inline fun <reified T> assertIsInstance(value: Any?) {
contract {
returns() implies T::class.isInstance(value))
}
if(value !is T){
throw java.lang.IllegalArgumentException("Incorrect type");
}
}
"Неподдерживаемая конструкция"
@UseExperimental(ExperimentalContracts::class)
inline fun <reified T> assertIsInstance(value: Any?, condition: Boolean = value is T) {
contract {
returns() implies condition
}
if(!condition)
throw IllegalArgumentException("Incorrect type");
}
Компилируется, но не включает умное приведение. Первоначальной мотивацией для этого была установка логического выражения перед контрактом, но контракты должны быть первой частью функции, которая делала это невозможным. Вы можете также удалить контракт; в этом случае это бесполезно.
Это была моя последняя попытка:
@UseExperimental(ExperimentalContracts::class)
inline fun assertIsInstance(value: Any?, cls: KClass<out Any>) {
contract {
returns() implies (cls.isInstance(value))
}
if(!cls.isInstance(value))
throw IllegalArgumentException("");
}
Еще одна "неподдерживаемая конструкция".
Каким-то образом я закончил с этим:
@UseExperimental(ExperimentalContracts::class)
inline fun assertIsInstance(value: Any?) {
contract {
returns() implies (value.hashCode() == 0)
}
if(value.hashCode() != 0)
throw java.lang.IllegalArgumentException();
}
Но это дает новую ошибку: only references to parameters are allowed in contract description
.
TL; DR:
Не похоже, что ты можешь. Подстановка, как я сделал во втором примере, не вызывает умного приведения, а остальные не работают из-за различных ошибок компилятора.
По крайней мере, на данный момент пути не существует. Конечно, вы можете открыть вопрос в репозитории Kotlin и попросить что-то подобное, но пока это не представляется возможным.