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

我试图写一些通用的代码,但不能摆脱Type of 'PROPERTY' is not a subtype of the overridden property错误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 -ed,但我怀疑这是最好的和唯一的方法。 有什么更好的吗?

毕竟我不明白,为什么subtypeA<subtypeB>不算作baseA<baseB>子类型,有人可以解释这一点吗?

首先, SubtypeA<B>SubtypeA<B>的一个子类型,所以问题出现在泛型参数的子类型中。

答案就在于Kotlin泛型方差 ,与Java相似。

为什么SubtypeA<SubtypeB>不算作BaseA<BaseB>子类型?

泛型默认是不变的,这意味着,即使在更简单的情况下,对于类A<T>A<SubtypeB>A<BaseB>也不是彼此的子类型,除非方差修饰符指定inout或Java通配符 )。

两种情况是可能的:

  • 如果你只想从你的类A的实例中取出 T实例,那么你可以使用修饰符: A<out T>

    这里A<SubtypeB>成为A<SubtypeB>一个子类型,因为从A<SubtypeB>你明显BaseB实例,反之亦然。

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

    在这里, A<BaseB>A<BaseB>的子类型,因为A<SubtypeB>每个实例也可以接收SubtypeB到方法中,反之亦然。

如果你同时从你的类A<T>传递A<T> ,那么A<T>的唯一选择是不变的,所以A<SubB>A<SuperB>都不是A<B>子类型:否则会导致与上述矛盾。

而这正是这种情况:在你的BaseP<B> ,你既是取V项目也是将其放入view属性,所以V只能是不变的,而BaseP<SubF>不是BaseP<SubF>的子类型, SubP<SubF>也不是。