返回
Kotlin 中的协变和逆变泛型:类型安全性与通用性
Android
2023-09-05 21:07:56
在 Kotlin 中,泛型是一项强大的特性,它允许您创建可与不同类型一起使用的类和方法。泛型通常通过使用尖括号和类型参数来定义,例如:
class GenericClass<T> {
fun genericMethod(t: T) {
// do something with t
}
}
该类可以与任何类型一起使用,例如:
val stringList: GenericClass<String> = GenericClass<String>()
stringList.genericMethod("Hello, world!")
val integerList: GenericClass<Int> = GenericClass<Int>()
integerList.genericMethod(42)
协变泛型
协变泛型允许您将子类型的实例传递给需要父类型实例的方法或类。例如,以下代码是允许的:
class Parent {
fun parentMethod() {
// do something
}
}
class Child : Parent() {
fun childMethod() {
// do something else
}
}
fun main() {
val parentList: List<Parent> = listOf(Parent(), Child())
for (parent in parentList) {
parent.parentMethod() // OK
// parent.childMethod() // Error: Child method not available in Parent reference
}
}
在上面的示例中,parentList
是一个包含 Parent
和 Child
实例的列表。我们可以在 parentList
上调用 parentMethod()
方法,因为 Child
是 Parent
的子类。但是,我们不能调用 childMethod()
方法,因为 Parent
的引用没有 childMethod()
方法。
逆变泛型
逆变泛型允许您从返回父类型实例的方法或类中接收子类型的实例。例如,以下代码是允许的:
class Parent {
fun parentMethod(): Parent {
// do something
return this
}
}
class Child : Parent() {
override fun parentMethod(): Child {
// do something else
return this
}
fun childMethod() {
// do something else
}
}
fun main() {
val child: Child = Child()
val parent: Parent = child.parentMethod() // OK
parent.parentMethod() // OK
// parent.childMethod() // Error: Child method not available in Parent reference
}
在上面的示例中,child.parentMethod()
返回一个 Child
实例,但我们将其赋给了一个 Parent
变量。这是允许的,因为 Child
是 Parent
的子类。我们可以在 parent
上调用 parentMethod()
方法,因为它是 Parent
的方法。但是,我们不能调用 childMethod()
方法,因为 Parent
的引用没有 childMethod()
方法。
协变和逆变泛型的安全性和限制
协变和逆变泛型是非常强大的特性,但它们也有一些安全性和限制。
- 协变泛型仅适用于方法或类的输入类型。您不能将协变泛型用于输出类型。
- 逆变泛型仅适用于方法或类的输出类型。您不能将逆变泛型用于输入类型。
- 协变和逆变泛型只能用于类和接口类型。它们不能用于基本类型或数组类型。
- 协变和逆变泛型只能用于单一类型参数。它们不能用于多个类型参数。
结论
协变和逆变泛型是 Kotlin 中非常强大的特性,它们允许您创建更灵活、更类型安全的泛型类和方法。但是,在使用协变和逆变泛型时,您需要了解它们的安全性限制。