Kotlin泛型的上界与下界

Kotlin 的泛型系统支持定义上界和下界约束,包括协变和逆变。这些特性使得 Kotlin 的泛型类型系统更加灵活和强大。下面是对 Kotlin 泛型上界和下界的详细说明:

泛型的上界 (Upper Bounds)

上界用于限制泛型类型参数的类型范围。默认情况下,泛型类型参数具有一个隐式的上界 Any?。你可以通过显式声明上界来进一步限制类型参数的类型范围。

示例

1.

默认隐式上界

|

1
class Box<T>(val value: T)  // T 的隐式上界是 Any?

|

2.

显式上界

|

1
class Box<T : Number>(val value: T)  // T 的上界是 Number,因此只能接受 Number 的子类型

|

3.

多重上界: 如果需要使用多个上界,可以使用 where 子句来进行声明。

|

1
fun <T> ensureAllNonNull(vararg args: T) where T : Any, T : Comparable<T> {    for (arg in args) {        checkNotNull(arg)        println(arg)    }}

|

泛型的下界 (Lower Bounds)

Kotlin 不直接提供显式声明下界的语法,但下界的概念可以通过协变和逆变来实现。协变和逆变是用于描述类型参数之间的子类型关系的概念,它们定义了类型参数在子类型化关系中的行为。

协变 (Covariance)

协变允许使用子类型来替代泛型类或接口的类型参数。在 Kotlin 中,协变使用关键字 out 来定义,表示泛型类型参数只能出现在输出位置(返回类型),不能出现在输入位置(函数参数)。

|

1
interface Source<out T> {    fun nextT(): T}fun demo(source: Source<String>) {    val anySource: Source<Any> = source // 协变,String 是 Any 的子类型,所以 Source<String> 可以赋值给 Source<Any>}

|

逆变 (Contravariance)

逆变允许使用超类型来替代泛型类或接口的类型参数。在 Kotlin 中,逆变使用关键字 in 来定义,表示泛型类型参数只能出现在输入位置(函数参数),不能出现在输出位置(返回类型)。

|

1
interface Consumer<in T> {    fun consume(item: T)}fun demo(consumer: Consumer<Number>) {    val intConsumer: Consumer<Int> = consumer // 逆变,Int 是 Number 的子类型,所以 Consumer<Number> 可以赋值给 Consumer<Int>}

|

使用示例

以下是一个综合示例如 Box 类和函数如何利用泛型的上界和协变逆变:

|

1
// 定义一个具有上界的泛型类class Box<T : Number>(val value: T)fun <T : Number> sum(value1: T, value2: T): Double {    return value1.toDouble() + value2.toDouble()}// 定义一个协变接口interface Source<out T> {    fun nextT(): T}// 定义一个逆变接口interface Consumer<in T> {    fun consume(item: T)}fun main() {    // 使用具有上界的泛型类    val intBox = Box(1)    val doubleBox = Box(1.0)    println(sum(1, 2))         // 输出: 3.0    println(sum(1.0, 2.0))     // 输出: 3.0    // 示例协变    val stringSource: Source<String> = object : Source<String> {        override fun nextT(): String {            return "Hello"        }    }    val anySource: Source<Any> = stringSource    println(anySource.nextT())  // 输出: Hello    // 示例逆变    val numberConsumer: Consumer<Number> = object : Consumer<Number> {        override fun consume(item: Number) {            println("Consumed $item")        }    }    val intConsumer: Consumer<Int> = numberConsumer    intConsumer.consume(10)  // 输出: Consumed 10}

|

总结

  • 上界:限制泛型类型参数的类型范围,默认是 Any?,可以显式地使用 :<类型> 来指定。

  • 下界:Kotlin 没有直接的下界语法,但可以通过协变(out)和逆变(in)来实现特定的行为。

  • 协变:使用 out 关键字表示,只能用于返回类型,允许将子类型泛型对象赋值给超类型的变量。

  • 逆变:使用 in 关键字表示,只能用于输入类型,允许将超类型泛型对象赋值给子类型的变量。