【问题标题】:Kotlin properties cannot be overridden with subinterfaceKotlin 属性不能被子接口覆盖
【发布时间】:2017-12-04 23:15:02
【问题描述】:

在下面的精简示例中,您能否解释为什么 Kotlin 编译器在覆盖我们进一步限制其类型时会抱怨(编译器消息:Var-property type is 'B', which is not a type of overriden public abstract var a: A)

interface A

interface B : A {
    fun someFunc():Boolean
}

class C : B {
    override fun someFunc(): Boolean {
        return true
    }
}

abstract class D {
    abstract var a: A
}

class E : D() {
    override var a : B = C()

    fun otherFunc() {
        println(a.someFunc())
    }
}

此外,编译器不会抱怨以下 sn-p:

open class G

class H : G()

abstract class F {
    abstract val g: G
}

class I : F() {
    override var g : H = H()
}

所以我猜想接口继承发生了一些事情,而类则没有。

【问题讨论】:

    标签: inheritance interface kotlin


    【解决方案1】:

    您的第一个代码 sn-p 无法编译,否则可能会出现这样的怪异现象:

    val d: D = E()
    d.a = object : A {}  // Some other sub-type of A, but definitely not a sub-type of B
    

    这实际上是 lack of method parameter covariance in Java 的变体(不是双关语) - 特别是考虑到 Kotlin 的 var 属性实际上只是 getter 和 setter 方法的语法糖。

    相反,您的第二个 sn-p 确实 编译,因为在这种情况下,协方差不是问题 - 基类 (F) 中没有设置器被覆盖,所以 "奇怪”我上面描述的是不可能的。

    【讨论】:

    • @SimonMarynissen - 这里的问题实际上在于可变性(即,您可以通过基类引用设置属性)。因此,一种解决方案是将其设为val 属性。但我想另一种解决方法是使用泛型 - 即abstract class D<T : A> { abstract var a: T } 和class E : D<B>() { override var a : B = C() }。不过,这并不适用于所有情况。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-19
    • 2011-05-27
    相关资源
    最近更新 更多