我的代码中有以下继承模式。
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.foo
和D.foo
的返回类型更改为MutableSet
时,编译器能够验证B.foo
的返回类型,但是我收到错误报告返回类型D.foo
不是MutableSet<B>
的子类型。
为什么Kotlin无法推断出这种形式的子类型,是否有任何工作而不会改变我的层次结构?
答案 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
上的实时示例