泛型类型参数的多重上界

移动开发 2026-07-12

在Kotlin中,我有一个接口和一个类。比如,接口A 和类B。

我想写一个带泛型的函数或类,使其泛型参数表示所有同时是A 和B 的子类型。怎么实现呢?

当我写 <T: A, B> 时,B被认为是第二个泛型,而不是T 的超类型。

下面是一段示例代码:

interface A
open class B

class C: B(), A
class D: B(), A
class E: B()
class F: A

fun <T: A> foo(x: T) {} // How to write generic here?

fun bar() {
    val c = C()
    val d = D()
    val e = E()
    val f = F()

    foo(c)  // This should be available
    foo(d)  // This should be available
    foo(e)  // This should throw error
    foo(f)  // This should throw error
}

我可以像下面这样引入另一个类型 P,并在 foo 中使用它:

open class P: B(), A
fun <T: P> foo(x: T) {}

但这将需要我把 CD 的声明改成如下:

class C: P()
class D: P()

我在实际项目中有很多这样的类,而且不想让作用域里再多出额外的类型来,因此我宁愿不走这条路。有没有更好的替代方案?

解决方案

这正是关键字 where 发挥作用的地方:

fun <T> foo(x: T)
        where T : A,
              T : B {
}

现在 x 的类型必须同时是 AB。编译器不仅会在 foo(e) 处报错,而且正如要求的那样,在 foo(f) 处也会报错:

参数类型不匹配:实际类型是 'F',但期望的类型为 'A & B'。

A & B 是一个 交叉类型,这是你不能显式声明的东西(因此也不会有 val x: A & B)。它只能被推断,但Kotlin能在幕后处理它,保持类型安全与类型推断按预期工作。

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章