我尝试编写一些通用代码,但无法解决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>
的子类型,有人可以解释一下吗?
答案 0 :(得分:8)
首先,SubtypeA<B>
是BaseA<B>
的子类型,因此问题出在通用参数子类型中。
答案在于Kotlin generics variance,与that of Java类似。
为什么
SubtypeA<SubtypeB>
不计算BaseA<BaseB>
的子类型?
默认情况下,泛型是不变的,这意味着,即使在更简单的情况下,对于类A<T>
,A<SubtypeB>
和A<BaseB>
也不是彼此的子类型,除非另有说明方差修饰符in
和out
(或Java wildcards)。
可能有两种情况:
如果您只想从您的班级T
的实例中获取 A
个实例,那么您可以使用out
修饰符:{{ 1}}。
此处A<out T>
成为A<SubtypeB>
的子类型,因为从A<BaseB>
开始,您显然可以采用A<SubtypeB>
的实例,反之亦然。
如果您只想传递 BaseB
进入您的班级&#39;方法,然后在类声明中使用T
修饰符:in
。
此处A<in T>
是A<BaseB>
的子类型,因为A<SubtypeB>
的每个实例也可以在方法中接收A<BaseB>
,但反之亦然。
如果你们都传递SubtypeB
来自你的T
课程,那么A<T>
的唯一选择是不变的,所以T
也不是A<SubB>
是A<SuperB>
的子类型:否则会导致与上述内容相矛盾。
情况确实如此:在A<B>
中,您正在使用BaseP<B>
项并将其放入V
属性,因此view
只能是不变的,V
不是BaseP<SubF>
的子类型,BaseP<BaseF>
也不是。