📜  Kotlin-泛型(1)

📅  最后修改于: 2023-12-03 14:43:42.367000             🧑  作者: Mango

Kotlin-泛型

Kotlin Logo

什么是泛型?

泛型是一种在编程语言中使用参数化类型的机制,它允许我们在定义类、函数或接口时使用类型参数,以便在使用时能够适应不同类型的数据。通过使用泛型,我们可以增加代码的灵活性、可重用性和类型安全性。

在 Kotlin 中,我们可以在声明类、函数或接口时使用尖括号 <T> 来定义类型参数。这个类型参数可以在定义的地方被用作普通类型一样,可以用于属性、参数和返回类型。

泛型类

泛型类是指在声明类时使用类型参数的类。对于一个泛型类,我们可以创建其具体类型的实例。

以下是一个示例代码来说明泛型类的使用:

class Stack<T> {
    private val elements = mutableListOf<T>()
    
    fun push(element: T) {
        elements.add(element)
    }
    
    fun pop(): T? {
        if (isEmpty()) return null
        return elements.removeAt(elements.size - 1)
    }
    
    fun isEmpty(): Boolean {
        return elements.isEmpty()
    }
}

// 使用泛型类
val stack = Stack<Int>()
stack.push(5)
stack.push(10)
println(stack.pop()) // 输出:10

在上面的例子中,我们创建了一个 Stack 泛型类,可以存储任意类型的元素。我们通过将 Stack 类型参数指定为 Int 来创建了一个存储整数的 stack 对象。我们可以使用 push 方法将元素压入栈中,使用 pop 方法从栈中弹出元素。

泛型函数

除了泛型类,我们还可以使用泛型函数。泛型函数是指在声明函数时使用类型参数的函数。

以下是一个示例代码来说明泛型函数的使用:

fun <T> printList(list: List<T>) {
    for (element in list) {
        println(element)
    }
}

// 使用泛型函数
printList(listOf(1, 2, 3)) // 输出:1 2 3
printList(listOf("Hello", "World")) // 输出:Hello World

在上面的例子中,我们定义了一个泛型函数 printList,它接收一个 List 参数,并打印出列表中的每个元素。我们可以在函数调用时指定具体的类型参数,也可以让编译器推断出类型参数。

泛型约束

有时候,我们可能希望泛型参数只能接受特定类型的参数。这时,我们可以使用泛型约束来限制类型参数的范围。

以下是一个示例代码来说明泛型约束的使用:

fun <T : Number> sumNumbers(a: T, b: T): T {
    return a + b
}

val intSum = sumNumbers(5, 10) // 可以传递整数类型
val doubleSum = sumNumbers(3.5, 7.2) // 可以传递浮点数类型

在上面的例子中,我们定义了一个泛型函数 sumNumbers,它要求类型参数 T 必须是 Number 或其子类。这样,我们不仅可以传递整数类型,还可以传递浮点数类型,而其他类型将无法通过编译。

变型(Variance)

Kotlin 中的泛型支持协变(covariant)和逆变(contravariant)。

  • 协变指的是如果子类的泛型参数类型是父类泛型参数类型的子类型,则可以将子类的实例赋值给父类的变量。
  • 逆变指的是如果子类的泛型参数类型是父类泛型参数类型的父类型,则可以将父类的实例赋值给子类的变量。

以下是一个示例代码来说明协变和逆变的使用:

// 定义一个协变接口
interface Producer<out T> {
    fun produce(): T
}

// 定义一个逆变接口
interface Consumer<in T> {
    fun consume(item: T)
}

fun main() {
    val stringProducer: Producer<String> = object : Producer<String> {
        override fun produce(): String {
            return "Hello World"
        }
    }
    
    val anyProducer: Producer<Any> = stringProducer // 协变,可以将子类赋值给父类
    
    println(anyProducer.produce()) // 输出:Hello World
    
    val numberConsumer: Consumer<Number> = object : Consumer<Number> {
        override fun consume(item: Number) {
            println("Consuming $item")
        }
    }
    
    val intConsumer: Consumer<Int> = numberConsumer // 逆变,可以将父类赋值给子类
    
    intConsumer.consume(5) // 输出:Consuming 5
}

在上面的例子中,我们定义了一个协变接口 Producer 和一个逆变接口 Consumer。我们创建了一个 stringProducer 对象,并将其赋值给 anyProducer 变量,这是协变的示例。然后,我们创建了一个 numberConsumer 对象,并将其赋值给 intConsumer 变量,这是逆变的示例。

总结

Kotlin 中的泛型在提高代码的灵活性、可重用性和类型安全性方面起到了重要作用。我们可以使用泛型类和泛型函数来处理多种类型的数据,并可以使用泛型约束来限制类型参数的范围。此外,对于协变和逆变,Kotlin 也提供了相应的支持,使得我们可以在需要时灵活地处理子类型和父类型之间的关系。

以上就是 Kotlin 中泛型的介绍,希望对你有所帮助!