问题描述
我正在KProperty1
上构建扩展函数。该函数需要接受扩展属性(R
)的值类型的参数,即使KProperty1
在类型参数R
中是协变的。
下面是一个稍微做作的例子,尽管我的使用更合法。
data class Data(val value: String)
fun <V> KProperty1<*, V>.setMagically(value: V) {
this.javaField?.set(null, value)
}
fun test() {
// I would like this to fail to compile
Data::value.setMagically(190)
}
编译器似乎正在为R
推断类型Any
,这是完全有效的,因为KProperty1<*, String> : KProperty1<*, Any>
我想说的是,对于我的特定情况,我实际上希望V
是不变的。我知道您可以使用out
和in
作为差异加宽器,但我不知道如何指定要在此情况下使用不变性覆盖KProperty1
上的协变批注。
值得注意的是,它在KMutableProperty1
中工作得很好,因为R
中是不变的。但我的代码也需要使用非可变属性。
对于上下文,我正在构建一些生成数据库查询的东西,这就是为什么我需要值是属性类型的子类,尽管我实际上并没有写入属性,但这个问题比我的特定属性处理情况更一般。
推荐答案
这在科特林中目前是不可能的。事实上,有一个内部注释支持这种行为(如果推断出Any
,但没有提到它在调用点的任何地方,则会导致编译器报告错误),并在kotlin-stdlib
中的多个位置使用它,但仍不鼓励在标准库之外使用它。
我们计划将此注释公之于众。有关更多详细信息,请查看KT-13198。