这一直困扰着我几个小时,特别是因为这是可能的:
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;博士:
看起来你不能。像我在第二个示例中所做的那样潜入它不会触发智能转换,并且由于各种编译器错误,其余部分不起作用。
至少目前看来,没有办法。你当然可以在 Kotlin 存储库中打开一个问题并要求这样的东西,但目前看来,这似乎是不可能的。