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>
也不是彼此的子类型,除非方差修饰符指定in
和out
或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>
也不是。