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关键字表示,只能用于输入类型,允许将超类型泛型对象赋值给子类型的变量。