Меня это беспокоит пару часов, тем более что такое возможно:
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 и попросить что-то подобное, но на данный момент это кажется невозможным.
person
Zoe
schedule
08.11.2018