问题
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
Tinstances out of instances of your classA, then you can useoutmodifier: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
Tinto your class' methods, then useinmodifier in your class declaration:A<in T>.And here
A<BaseB>is a subtype ofA<SubtypeB>, because every instance ofA<BaseB>can also receiveSubtypeBinto 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