返回

轻松掌握 Kotlin 泛型:形参与实参

Android

Kotlin中的形参和实参:掌握泛型的关键

什么是泛型?

泛型是编程语言中的一种特性,允许您编写代码,该代码可以在多种类型上运行,而无需显式指定类型。它提高了代码的可重用性和灵活性。

形参和实参

在泛型编程中,形参就像占位符,表示泛型类型。它们在函数或类定义中使用尖括号表示,例如 <T>。实参是指定泛型类型实际类型的具体类型。

协变和逆变

协变和逆变了形参和实参之间的关系。

  • 协变形参(out) :形参可以是实参的子类。这意味着您可以将子类作为实参传递给父类形参。例如,out List<Animal> 可以接受 List<Dog>,因为 DogAnimal 的子类。
  • 逆变形参(in) :形参可以是实参的父类。这意味着您可以将父类作为实参传递给子类形参。例如,in Animal 可以接受 Dog,因为 DogAnimal 的子类。

不变形参

如果形参既不是协变也不是逆变,则称为不变形参。不变形参必须与实参类型完全匹配。例如,List<Animal> 只能接受 List<Animal>,不能接受 List<Dog>List<Object>

星投影

星投影(*)是一种特殊形式的形参,表示任何类型。它允许泛型方法或类处理不同类型的对象。例如,List<*> 可以接受任何类型的列表,无论元素类型如何。

示例

以下是形参和实参如何协同工作的示例:

class Animal(val name: String)
class Dog(name: String) : Animal(name)
class Cat(name: String) : Animal(name)

fun printAnimalNames(animals: List<Animal>) {
    for (animal in animals) {
        println(animal.name)
    }
}

val dogList: List<Dog> = listOf(Dog("Buddy"), Dog("Max"))
val catList: List<Cat> = listOf(Cat("Kitty"), Cat("Fluffy"))

printAnimalNames(dogList) // 编译通过
printAnimalNames(catList) // 编译通过

在上面示例中,printAnimalNames() 函数接受 List<Animal> 类型的参数。dogListcatList 都是 Animal 的子类,因此函数可以接受它们作为实参。

结论

理解形参和实参的概念对于编写使用 Kotlin 泛型的安全和可维护的代码至关重要。掌握这些概念将使您能够编写出色的代码,提高可重用性并减少错误。

常见问题解答

1. 如何判断形参是协变还是逆变?

查看形参声明前是否带有 outinout 表示协变,in 表示逆变。

2. 为什么不变形参很重要?

不变形参确保类型安全。它防止您将错误类型的对象传递给泛型方法或类。

3. 星投影有什么好处?

星投影允许您编写处理不同类型对象的通用代码。它提高了代码的可重用性。

4. 如何在 Kotlin 中编写协变或逆变函数?

使用 outin 关键字指定形参的协变性或逆变性。例如:

fun printAnimalNames(animals: out List<Animal>) {
    // ...
}

5. 编写使用泛型的代码时应注意哪些事项?

  • 确保使用正确的协变性或逆变性。
  • 避免使用不变形参,除非绝对必要。
  • 考虑使用星投影提高代码的可重用性。
  • 编写单元测试以验证泛型代码的正确性。