Kotlin:覆盖子类型中的泛型属性

Ale*_*nov 7 generics overriding kotlin

我试图编写一些通用代码,但无法摆脱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'
}
Run Code Online (Sandbox Code Playgroud)

我发现错误可以 - @Suppress但我怀疑它是最好的也是唯一的方法.还有更好的东西吗?

毕竟我无法理解,为什么subtypeA<subtypeB>不算作子类型baseA<baseB>,有人可以解释一下吗?

hot*_*key 8

首先,SubtypeA<B>是子类型BaseA<B>,所以问题在于泛型参数子类型.

答案在于Kotlin泛型方差,它类似于Java.

为什么SubtypeA<SubtypeB>不算作子类型BaseA<BaseB>

泛型是默认的,这意味着,即使在简单的情况下,一类不变A<T>,A<SubtypeB>并且A<BaseB>除非另有由方差修饰符指定不是彼此的亚型inout(或爪哇通配符).

有两种情况可能:

  • 如果你只想 T实例您的类的实例A,那么你可以使用out修改器:A<out T>.

    这里A<SubtypeB>成为一个子类型A<BaseB>,因为从A<SubtypeB>你可以明显地看到实例BaseB,而不是相反.

  • 如果你只想传递 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>,也不是SubP<SubF>.