You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin泛型上界场景下SubFoo是否为Foo<A>子类型的疑问

结论: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 17:20:31