Swift 中的泛型:完整指南及代码示例

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

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

开始课程

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



泛型(泛型编程)是 Swift 语言中最强大、最基础的功能之一。它允许您编写灵活、类型安全且可重用的代码,避免重复。如果您曾经使用过 Array<Int>、Dictionary<String, Any> 或 Optional<T>,那么您已经接触过泛型。在本文中,我们将探讨为何需要泛型、如何正确使用它们,并介绍适用于 iOS/macOS 开发的实用示例。



为什么 Swift 中需要泛型?



泛型解决的主要问题是:需要为不同的数据类型编写相同的代码。没有泛型,您将不得不为 Int、String、Double 以及自定义结构体创建单独的函数。这会导致代码重复、错误增多,并增加维护难度。



泛型的主要优势:

  • 类型安全:编译器在编译阶段检查类型,防止运行时错误。
  • 代码重用:一个函数或类型可以处理任何数据类型。
  • 性能:Swift 中的泛型通过特化实现——编译器为每个具体类型生成优化代码,其性能与手动编写重复代码相当。
  • 可读性与抽象性:代码更简洁、更具表现力。


来看一个简单的例子。假设我们需要一个交换两个变量值的函数。没有泛型时,必须这样写:



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}// ... 每个类型都要这样写


使用泛型后,解决方案变得通用:



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

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

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


如您所见,<T> 是一个类型占位符。编译器会在调用函数时自动推断具体类型。



泛型函数和类型



泛型不仅可用于函数,还可用于自定义类型:结构体、类和枚举。



泛型函数

除了简单的占位符,还可以对类型施加约束。例如,一个仅适用于实现了 Equatable 协议的类型的函数:



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

let numbers = [1, 5, 3, 12]if let index = findIndex(of: 5, in: numbers) { print("找到索引: \\(index)") // 输出:找到索引: 1}


约束 <T: Equatable> 确保类型 T 定义了 == 运算符。



泛型类型(结构体和类)

我们来创建一个简单的栈——一种遵循 LIFO(后进先出)原则的数据结构:



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

var intStack = Stack<Int>()intStack.push(10)intStack.push(20)print(intStack.pop() ?? 0) // 20

var str

博客

书籍推荐