generics - Kotlin:覆盖子类型中的通用属性

标签 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'
}

我发现错误可能是@Suppress -ed,但我怀疑这是最好的也是唯一的方法。有更好的吗?

毕竟我不明白,为什么 subtypeA<subtypeB>不计为 baseA<baseB> 的子类型,有人能解释一下吗?

最佳答案

首先,SubtypeA<B>BaseA<B> 的子类型,所以问题出在泛型参数子类型上。

答案在于Kotlin generics variance ,类似于 that of Java .

Why doesn't SubtypeA<SubtypeB> count as subtype of BaseA<BaseB>?

默认情况下泛型是不变的,这意味着,即使在更简单的情况下,对于一个类 A<T> , A<SubtypeB>A<BaseB>除非方差修饰符 in 另有说明,否则它们不是彼此的子类型和 out (或 Java wildcards)。

可能有两种情况:

  • 如果你只想服用 T您的类(class)实例中的实例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往/返你的类(class)A<T> , 那么 T 的唯一选项它是不变的,所以 A<SubB>也不是 A<SuperB>A<B> 的子类型: 否则会导致与上面的矛盾。

情况正是如此:在您的 BaseP<B> 中,你们都在拿V的元素并将它们放入 view属性(property),所以 V只能是不变的,BaseP<SubF>不是 BaseP<BaseF> 的子类型, SubP<SubF> 也不是.

关于generics - Kotlin:覆盖子类型中的通用属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35431249/

相关文章:

java - 返回泛型类型的新实例,其中 T 设置为给定 arg 的类型

java - 如何使用一个对象访问所有子方法?

c# - 使哈希表不可变

kotlin - 当接收者从上下文中获知时,缩短对类方法的引用

android - 如何通过 Android/Kotlin App 上的 Koin 注入(inject)在 BaseActivity 中初始化/注入(inject)通用 ViewModel

c# - 循环泛型类型参数

java - 使用 -Xlint 进行编译,获得对 add(E) 的未经检查的调用

依赖于某些参数的 Java 类

java - Spring集成入站 channel 适配器中的覆盖方法

android - 如何使 UI 调度程序立即恢复继续