前言
在 Kotlin 中,泛型是一种强大的特性,它允许你编写可复用的代码,这些代码可以处理不同类型的数据,而不需要为每种数据类型都编写特定的实现。
泛型在类、接口、函数等方面都有广泛应用,下面将详细介绍 Kotlin 中泛型的相关内容。
泛型类和泛型接口
泛型类和泛型接口在定义时会使用类型参数,这些类型参数在创建类的实例或实现接口时会被具体的类型所替代。
class
1 | class ResultVo<T> { |
data class
1 | data class ResultVo<out T>( |
泛型函数
泛型函数允许你在函数级别使用类型参数,使得函数可以处理不同类型的数据。
示例代码
1 | fun <T> printItem(item: T) { |
代码解释
printItem<T>
是一个泛型函数,<T>
表示该函数使用了一个类型参数T
。在调用printItem
函数时,Kotlin 会根据传入的参数自动推断T
的具体类型。
泛型约束
泛型约束允许你限制类型参数必须是某个特定类型或其子类型,这样可以在泛型代码中使用特定类型的方法和属性。
示例代码
1 | // 定义一个接口 |
代码解释
Printable
是一个接口,Person
类实现了该接口。printAll<T : Printable>
是一个泛型函数,使用了泛型约束T : Printable
,表示类型参数T
必须是Printable
接口的实现类。在函数内部,可以调用T
类型对象的printInfo
方法。
变型(协变、逆变和不变)
Kotlin 中的变型用于处理泛型类型之间的子类型关系,分为协变、逆变和不变三种情况。
协变(out
)
协变允许泛型类型作为生产者,只能从中读取数据,不能写入数据。
示例代码
1 | // 协变泛型类 |
代码解释
Producer<out T>
是一个协变泛型接口,使用out
关键字表示协变。StringProducer
类实现了Producer<String>
接口。- 由于协变的特性,
Producer<String>
类型的对象可以赋值给Producer<Any>
类型的变量。
逆变(in
)
逆变允许泛型类型作为消费者,只能向其中写入数据,不能读取数据。
示例代码
1 | // 逆变泛型类 |
代码解释
Consumer<in T>
是一个逆变泛型接口,使用in
关键字表示逆变。AnyConsumer
类实现了Consumer<Any>
接口。- 由于逆变的特性,
Consumer<Any>
类型的对象可以赋值给Consumer<String>
类型的变量。
不变
如果泛型类型既不是协变也不是逆变,则是不变的,即泛型类型之间不存在子类型关系。
星投影(*
)
星投影用于在不知道具体类型参数时使用泛型类型。
示例代码
1 | fun printElements(list: List<*>) { |
代码解释
List<*>
表示一个泛型列表,其中的元素类型未知。printElements
函数可以接受任何类型的列表作为参数。
通过以上介绍,你可以了解到 Kotlin 中泛型的基本概念和使用方法,包括泛型类、泛型接口、泛型函数、泛型约束、变型和星投影等。泛型可以提高代码的复用性和类型安全性,是 Kotlin 中非常重要的特性之一。