Swift中的泛型:为何需要及如何使用

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

什么是 Swift 中的 Generics 以及为什么需要它们



Generics(泛型编程)是 Swift 语言最强大的特性之一。它允许您编写灵活、可重用的代码,这些代码可以处理任何数据类型,同时保持严格的类型安全。您无需为 Int、String、Double 和其他类型创建单独的函数或结构体,只需编写一个通用代码,该代码会在编译时适应具体的类型。



想象一下,您需要编写一个交换两个值的函数。没有 Generics,您必须为每种类型创建重载:



func swapInts(_ a: inout Int, _ b: inout Int) {    let temp = a    a = b    b = temp}

func swapStrings(_ a: inout String, _ b: inout String) { let temp = a a = b b = temp}


使用 Generics,只需一行代码即可完成:



func swapValues<T>(_ a: inout T, _ b: inout T) {    let temp = a    a = b    b = temp}

var x = 10, y = 20swapValues(&x, &y) // 适用于 Int

var str1 = "Hello", str2 = "World"swapValues(&str1, &str2) // 适用于 String


Generics 的主要优势



  • 类型安全: 编译器在编译阶段检查类型,消除运行时错误
  • 代码重用: 一次编写的代码适用于任何类型
  • 性能: Swift 中的 Generics 在编译器层面实现,不会损失执行速度
  • 可读性: 减少代码重复,使代码更简洁


Generic 函数和类型参数



Generic 函数使用尖括号 <> 声明,其中指定了类型参数(通常用字母 T 表示,但可以使用任何名称)。类型参数作为一个占位符,在函数调用时会被实际类型替换。



示例:在数组中查找元素



func findIndex<T: Equatable>(of value: T, in array: [T]) -> Int? {    for (index, element) in array.enumerated() {        if element == value {            return index        }    }    return nil}

let numbers = [1, 5, 3, 12, 7]if let index = findIndex(of: 12, in: numbers) { print("数字 12 的索引: \\(index)") // 数字 12 的索引: 3}

let names = ["Anna", "Boris", "Victor"]if let index = findIndex(of: "Boris", in: names) { print("名字 Boris 的索引: \\(index)") // 名字 Boris 的索引: 1}


注意约束条件 T: Equatable。这是一个类型约束——我们要求类型 T 支持 Equatable 协议,否则比较操作 == 将无法进行。



Generic 类型:结构体、类和枚举



Generics 不仅适用于函数,也适用于自定义类型。这使得创建通用数据容器成为可能。



创建 Generic 栈



经典示例是数据结构 Stack(栈),它可以处理任何类型:



struct Stack<Element> {    private var items: [Element] = []        mutating func push(_ item: Element) {        items.append(item)    }        @discardableResult    mutating func pop() -> Element? {        return items.popLast()    }        func peek() -> Element? {        return items.last    }        var isEmpty: Bool {        return items.isEmpty    }}

// 使用示例var intStack = Stack<Int>()intStack.push(10)intStack.push(20)print(intStack.pop() ?? "") // 20

var stringStack = Stack<String>()stringStack.push("Swift")stringStack.push("Generics")print(stringStack.pop() ?? "") // Generics


Generic 枚举



枚举也可以是

博客

书籍推荐