问题
I trying to write some generic code, but can't get rid of Type of 'PROPERTY' is not a subtype of the overridden property
error.
Simplified version of my code:
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'
}
I found that error can be @Suppress
-ed, but I doubt it is best and only way. Is there something better?
And after all I can't understand, why subtypeA<subtypeB>
doesn't count as subtype of baseA<baseB>
, can someone explain this?
回答1:
First, SubtypeA<B>
is a subtype of BaseA<B>
, so the problem is in the generics parameters subtyping.
The answer lies in Kotlin generics variance, which is similar to that of Java.
Why doesn't
SubtypeA<SubtypeB>
count as subtype ofBaseA<BaseB>
?
The generics are invariant by default, which means that, even in simpler case, for a class A<T>
, A<SubtypeB>
and A<BaseB>
are not subtypes of each other unless otherwise is specified by variance modifiers in
and out
(or Java wildcards).
Two cases are possible:
If you want only to take
T
instances out of instances of your classA
, then you can useout
modifier:A<out T>
.Here
A<SubtypeB>
becomes a subtype ofA<BaseB>
, because fromA<SubtypeB>
you can obviously take instances ofBaseB
, and not vice versa.If you want only to pass
T
into your class' methods, then usein
modifier in your class declaration:A<in T>
.And here
A<BaseB>
is a subtype ofA<SubtypeB>
, because every instance ofA<BaseB>
can also receiveSubtypeB
into the methods, but not vice versa.
If you both pass and take T
to/from your class A<T>
, then the only option for T
it is to be invariant, so that neither A<SubB>
nor A<SuperB>
are subtypes of A<B>
: otherwise would lead to a contradiction to the above.
And this is exactly the case: in your BaseP<B>
, you are both taking items of V
and putting ones into view
property, so V
can only be invariant, and BaseP<SubF>
is not a subtype of BaseP<BaseF>
, neither is SubP<SubF>
.
来源:https://stackoverflow.com/questions/35431249/kotlin-override-generic-property-within-subtype