Kotlin 中泛型的子类型问题
Subtype issues with generics in 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 return 设置时,编译器能够确定 Set<D>
是 Set<B>
和 Set<C>
的子类型。但是,当我将 B.foo
和 D.foo
的 return 类型更改为 MutableSet
时,编译器能够验证 B.foo
的 return 类型但我收到一条错误报告,指出 D.foo
的 return 类型不是 MutableSet<B>
.
的子类型
为什么 Kotlin 无法推断出这种形式的子类型,是否有任何解决方法而不需要彻底改变我的层次结构?
覆盖函数的 return 类型 必须 是被覆盖函数的子类型。在您的示例中,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
上的实例
我的代码中有以下继承模式。
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 return 设置时,编译器能够确定 Set<D>
是 Set<B>
和 Set<C>
的子类型。但是,当我将 B.foo
和 D.foo
的 return 类型更改为 MutableSet
时,编译器能够验证 B.foo
的 return 类型但我收到一条错误报告,指出 D.foo
的 return 类型不是 MutableSet<B>
.
为什么 Kotlin 无法推断出这种形式的子类型,是否有任何解决方法而不需要彻底改变我的层次结构?
覆盖函数的 return 类型 必须 是被覆盖函数的子类型。在您的示例中,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
上的实例