Kotlin中泛型的子类型问题

时间:2015-05-06 04:15:05

标签: generics override kotlin

我的代码中有以下继承模式。

trait  A {
    fun foo(): Set<A>
}

trait B : A {
    override fun foo(): MutableSet<B>
}

trait C : A {
    override fun foo(): Set<C>

}

trait D : C, B {
    override fun foo(): MutableSet<D>
}

当B和D返回集合时,编译器能够确定Set<D>Set<B>Set<C>的子类型。但是,当我将B.fooD.foo的返回类型更改为MutableSet时,编译器能够验证B.foo的返回类型,但是我收到错误报告返回类型D.foo不是MutableSet<B>的子类型。

为什么Kotlin无法推断出这种形式的子类型,是否有任何工作而不会改变我的层次结构?

1 个答案:

答案 0 :(得分:2)

覆盖函数的返回类型必须是被覆盖函数的子类型。在您的示例中,MutableSet<D>不是MutableSet<B>的子类型。如果是,类似的代码可能会在运行时导致异常:

trait B {
    fun foo(): MutableSet<B>
}

trait D : B {
    override fun foo(): MutableSet<D>

    fun onlyInD() {}
}

class BImpl : B {
    override fun foo() = null!!
}

class DImpl : D {
    private val set = java.util.HashSet<D>()

    override fun foo() = set
}    

fun main(args: Array<String>) {
    val impl = DImpl()
    // two variables pointing to the same instance
    val b: B = impl 
    val d: D = impl

    b.foo().add(BImpl())

    // ClassCastException on the next line: BImpl is not an instance of D
    d.foo().first().onlyInD()
}

请参阅try.kotl.in

上的实时示例