Kotlin:覆盖子类型中的泛型 属性

Kotlin: override generic property within subtype

我试图编写一些通用代码,但无法摆脱 Type of 'PROPERTY' is not a subtype of the overridden property 错误。

我的代码的简化版本:

abstract class BaseP<V> {
    var view: V? = null
}

abstract class BaseF {
    fun smth() {
        pp.view = this
    }
    abstract val pp: BaseP<BaseF>
}

abstract class SubF: BaseF() {
    abstract override val pp: BaseP<SubF>
    // Error:(20, 30) Type of 'pp' is not a subtype of the overridden property 'public abstract val pp: BaseP<BaseF> defined in BaseF'
}

我发现可以 @Suppress 编辑错误,但我怀疑这是最好且唯一的方法。还有更好的吗?

毕竟我无法理解,为什么 subtypeA<subtypeB> 不算作 baseA<baseB> 的子类型,有人可以解释一下吗?

首先,SubtypeA<B>BaseA<B> 的子类型,所以问题出在泛型参数子类型上。

答案就在Kotlin generics variance, which is similar to that of Java.

Why doesn't SubtypeA<SubtypeB> count as subtype of BaseA<BaseB>?

泛型默认是不变的,这意味着,即使在更简单的情况下,对于 class A<T>A<SubtypeB>A<BaseB> 也不是每个的子类型other 除非由方差修饰符 inout(或 Java wildcards)另有规定。

可能有两种情况:

  • 如果您只想从 class A 的实例中 获取 T 个实例,那么您可以使用 out 修饰符:A<out T>.

    此处 A<SubtypeB> 成为 A<BaseB> 的子类型,因为从 A<SubtypeB> 显然可以获取 BaseB 的实例,反之亦然。

  • 如果您只想将 传递 T 到您的 class' 方法中,则在中使用 in 修饰符您的 class 声明:A<in T>.

    而这里的A<BaseB>A<SubtypeB>的子类型,因为A<BaseB>的每个实例也可以将SubtypeB接收到方法中,但反之则不行。

如果你都通过 T to/from 你的 class A<T>,那么 T 的唯一选择就是保持不变,所以A<SubB>A<SuperB> 都不是 A<B> 的子类型:否则会导致与上述矛盾。

情况确实如此:在你的 BaseP<B> 中,你同时获取了 V 的项目并将其中的项目放入 view 属性,所以 V 只能是不变的,并且 BaseP<SubF> 不是 BaseP<BaseF> 的子类型,也不是 SubP<SubF>.