我试图编写一些通用代码,但无法摆脱Type of 'PROPERTY' is not a subtype of the overridden property
error.
我的代码的简化版本:
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>
,有人可以解释一下吗?
First, SubtypeA<B>
是一个子类型BaseA<B>
,所以问题出在泛型参数子类型上。
答案在于Kotlin 泛型方差 https://kotlinlang.org/docs/reference/generics.html#variance,这类似于爪哇的 https://dzone.com/articles/covariance-and-contravariance.
为什么不SubtypeA<SubtypeB>
算作子类型BaseA<BaseB>
?
默认情况下,泛型是不变的,这意味着即使在更简单的情况下,对于一个类A<T>
, A<SubtypeB>
and A<BaseB>
除非方差修饰符另有指定,否则不是彼此的子类型in
and out
(or Java 通配符 https://docs.oracle.com/javase/tutorial/extra/generics/wildcards.html).
可能有两种情况:
-
如果你只想take T
类实例之外的实例A
,那么你可以使用out
修饰符:A<out T>
.
Here A<SubtypeB>
成为的子类型A<BaseB>
,因为从A<SubtypeB>
你显然可以举个例子BaseB
,反之则不然。
-
如果你只想pass T
进入你的类的方法,然后使用in
类声明中的修饰符:A<in T>
.
和这里A<BaseB>
是一个子类型A<SubtypeB>
,因为每个实例A<BaseB>
还可以收到SubtypeB
进入方法,但反之则不然。
如果你都通过并接受T
往返您的班级A<T>
,那么唯一的选择是T
它是不变的,因此既不A<SubB>
nor A<SuperB>
是以下子类型A<B>
: 否则会导致与上述矛盾。
情况正是如此:在你的BaseP<B>
,你们俩都拿了以下物品V
并将其放入view
财产,所以V
只能是不变的,并且BaseP<SubF>
不是 的子类型BaseP<BaseF>
, 既不是SubP<SubF>
.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)