我尝试编写一个assert函数,检查给定对象是否为T
类型:
@UseExperimental(ExperimentalContracts::class)
inline fun <reified T> assertIsInstance(value: Any?) {
contract {
returns() implies (value is T)
}
Assertions.assertThat(value).isInstanceOf(T::class.java)
}
该函数使用AssertJ来执行具体的Assert,但我愿意让编译器知道在执行后,value
的类型是T
,因此可以进行smartcast。看起来这不起作用,因为:Error in contract description: references to type parameters are forbidden in contracts
有没有其他方法可以实现这种行为?这里的问题是什么?这最终可能吗?
(使用Kotlinv1.3)
4条答案
按热度按时间ewm0tg9j1#
这已经困扰了我几个小时,特别是因为这是可能的:
编译器显然能够理解这些,所以这可能是契约本身的限制。
我已经花了一段时间来尝试想出一些变通方法。供参考:
“无支撑结构”
编译,但不启用智能转换。其背后的原始动机是在合约前面放置一个布尔值,但合约需要成为函数的第一部分,这使得这是不可能的。您还不如删除合约;在这种情况下是没用的。
这是我最后一次尝试:
另一个“无支撑结构”。
不知怎的,我最终得到了这个:
但这会产生一个新的错误:
only references to parameters are allowed in contract description
.TL;DR:
看起来你做不到。像我在第二个例子中所做的那样偷偷地把它放进去并不会触发智能强制转换,其余的由于各种编译器错误而无法工作。
至少现在,似乎没有办法。你当然可以在Kotlin仓库中打开一个问题,并要求这样的东西,但现在,这似乎是不可能的。
u91tlkcl2#
在某些时候,IDE中对此类构造的支持存在一些(技术上的)问题,但将来可能会放宽这一限制。
8gsdolmq3#
https://pl.kotl.in/uFCsGWEZm
ep6jt1vc4#
我有一个解决方案,通过了我在Kotlin1.8.20上的单元测试: