强制类型参数在声明站点处协变时在使用站点处是不变的

时间:2017-11-09 00:14:57

标签: generics reflection kotlin covariance generic-variance

我正在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)
}

似乎编译器推断Any的{​​{1}}类型,这是完全有效的,因为R

我想说的是,就我的具体情况而言,我实际上希望KProperty1<*, String> : KProperty1<*, Any>不变。我知道你可以使用Vout作为方差扩展器,但是我无法弄清楚如何指定我想要覆盖in上的协变注释,并且这种情况具有不变性。

值得注意的是,它与KProperty1一起使用效果很好,因为它在KMutableProperty1中不变。但我的代码也需要使用非可变属性。

对于上下文,我构建了一些生成数据库查询的东西,这就是为什么我需要将值作为属性类型的子类,即使我实际上没有写入属性,但是这个问题比我具体的财产处理案例更为笼统。

1 个答案:

答案 0 :(得分:1)

目前Kotlin无法做到这一点。实际上,有一个内部注释可以启用此行为(如果推断出echo 12345 | grep -o '^\([[:digit:]]\)\{1,4\}' ,则会导致编译器报告错误,尽管在提到的呼叫站点处没有提到)并且它已在多个地方使用$,但仍然不鼓励在标准库之外使用它。

我们计划公开这个注释。有关详细信息,请查看KT-13198