Kotlin泛型上界场景下SubFoo是否为Foo<A>子类型的疑问
SubFoo 是否为 Foo 的子类型?相关代码能否编译?
结论:SubFoo 不是 Foo 的子类型,你写的两行代码都无法通过 Kotlin 编译器的检查。
核心原因:Kotlin 泛型默认是不变的
Kotlin 中,泛型类默认是**不变(invariant)**的——也就是说,即使 B 是 A 的子类型,Foo<B> 和 Foo<A> 之间也不存在任何子类型关系。
你的 Foo 类定义中包含一个接受 T 类型参数的方法:
open class Foo<T : A> { fun doSomething(temp: T) }
假设允许 SubFoo(即 Foo<B> 的子类)赋值给 Foo<A> 类型的变量,那么调用 doSomething 时理论上可以传入任意 A 类型的实例(比如 A()),但实际的 SubFoo 实现只能接受 B 类型的参数,这会导致类型安全问题。为了避免这种情况,编译器直接禁止了这种类型转换。
关于 SubFoo 的继承关系
SubFoo 是 Foo<B> 的子类,但由于 Foo<B> 和 Foo<A> 之间没有子类型关系,SubFoo 也无法向上转型为 Foo<A>。因此:
input(inputParam)会报错:编译器需要Foo<A>,但实际传入的是SubFoo(即Foo<B>),类型不匹配。val ret: Foo<A> = output()同样报错:output()返回的SubFoo无法赋值给Foo<A>类型的变量。
什么时候能实现你想要的效果?
如果希望 Foo<B> 可以作为 Foo<A> 的子类型,你需要将 Foo 声明为协变(covariant),但协变有严格的限制:泛型参数只能用于输出位置(比如作为返回值),不能用于输入位置(比如方法参数)。
但你的 Foo 类中 T 被用作方法参数(输入位置),所以无法将 T 声明为 out(协变修饰符)——编译器会直接报错:Type parameter T is declared as 'out' but occurs in 'in' position in type T。
内容的提问来源于stack exchange,提问作者CoolRobloxKid12
相关产品推荐
相关产品推荐

