Kotlin 快速入门:泛型概念
泛型是Kotlin语言中一个强大的特性,它允许你编写更通用和可重用的代码。通过泛型,你可以轻松地创建可以处理多种类型的数据结构和算法。以下是Kotlin中泛型的几个重要概念及其使用方式:
泛型类和泛型函数
泛型类:
泛型类让你可以定义一个类,它可以处理不同类型的数据。例如:class Box<T>(t: T) {
var value = t
}
fun main() {
val intBox = Box(1)
val stringBox = Box("Hello")
println(intBox.value) // 输出 1
println(stringBox.value) // 输出 Hello
}
在这个例子中,
Box
是一个泛型类,其中的T
是一个类型参数,可用于任何类型。泛型函数:
和泛型类类似,泛型函数是在函数中使用类型参数。例如:fun <T> singletonList(item: T): List<T> {
return listOf(item)
}
fun main() {
val stringList = singletonList("Hello")
val intList = singletonList(42)
println(stringList) // 输出 [Hello]
println(intList) // 输出 [42]
}
泛型约束
有时候你需要限制泛型的类型。例如,你可能只想允许某个类型的子类型。Kotlin通过泛型约束实现:
fun <T : Comparable<T>> sort(list: List<T>) {
// 排序逻辑
}
fun main() {
sort(listOf(1, 2, 3)) // 可行,因为 Int 实现了 Comparable<Int>
// sort(listOf("one", 2, 3)) // 会报错,因为混合类型不符合约束
}
型变与协变、逆变
Kotlin提供了声明性型变的概念,包括协变 (out
) 和逆变 (in
) 标注,以确保类型安全。
协变(Covariance -
out
):
协变允许你安全地从一个数据结构中读取数据。例如,如果一个类Producer<out T>
只产生T
类型的对象而不消耗它们,那么它就是协变的。interface Producer<out T> {
fun produce(): T
}
// 可以将一个 Producer<String> 赋值给 Producer<Any>
fun demo(producer: Producer<String>) {
val anyProducer: Producer<Any> = producer
}
逆变(Contravariance -
in
):
逆变允许你安全地将对象写入到数据结构中。例如,如果一个类Consumer<in T>
只消耗T
类型的对象而不产生它们,那么它就是逆变的。interface Consumer<in T> {
fun consume(item: T)
}
// 可以将一个 Consumer<Any> 赋值给 Consumer<String>
fun demo(consumer: Consumer<Any>) {
val stringConsumer: Consumer<String> = consumer
}
星投影
有时候你可能会想使用泛型类型,但是不在乎具体的类型参数是什么。在这种情况下,可以使用星投影(*
):
fun printContents(list: List<*>) {
println(list.joinToString())
}
fun main() {
printContents(listOf("Hello", "World"))
printContents(listOf(1, 2, 3))
}
在这个例子中,List<*>
是一种可以表示任何类型的 List
。
总结
Kotlin的泛型提供了灵活性和类型安全性,可以让你编写更加通用和可重用的代码。理解泛型类、泛型函数、型变(协变和逆变)以及星投影可以帮助你充分利用Kotlin的类型系统。掌握这些概念将大大提高你在Kotlin编程中的能力和效率。