Swift — 泛型(Generics)

泛型(Generics)是 Swift 语言中的强大特性,它允许你编写灵活且可重用的代码。通过使用泛型,你可以让函数、方法、类、结构体和枚举适用于任何类型,而不需要重复编写相同的代码。泛型有助于编写更加抽象和通用的代码,从而提高代码的复用性和类型安全性。

泛型在 Swift 中通过在尖括号 <T> 中声明类型参数来实现,以下是引入泛型的几个基本内容:

泛型函数 #

泛型函数允许你定义一个独立于任何特定类型的函数。例如,下面是一个非泛型的函数:

func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}

使用泛型后,可以将函数改写为处理任意类型:

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

你可以使用这个泛型函数来交换任意类型的两个值:

var int1 = 1
var int2 = 2
swapTwoValues(&int1, &int2) // int1 现在是 2,int2 是 1

var str1 = "Hello"
var str2 = "World"
swapTwoValues(&str1, &str2) // str1 现在是 "World",str2 是 "Hello"

泛型类型 #

除了泛型函数,你还可以定义泛型类型,包括类、结构体和枚举。以下是一个使用泛型的栈(Stack)结构体示例:

struct Stack<Element> {
    private var items: [Element] = []

    mutating func push(_ item: Element) {
        items.append(item)
    }

    mutating func pop() -> Element? {
        return items.popLast()
    }

    func top() -> Element? {
        return items.last
    }

    var isEmpty: Bool {
        return items.isEmpty
    }
}

var intStack = Stack<Int>()
intStack.push(1)
intStack.push(2)
print(intStack.top()!) // 输出 2

var stringStack = Stack<String>()
stringStack.push("Hello")
stringStack.push("World")
print(stringStack.top()!) // 输出 "World"

泛型约束 #

你可以在泛型类型或函数上添加约束,要求类型参数必须符合特定的协议或父类。例如,下面是一个要求类型参数遵循 Equatable 协议的函数:

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

let numbers = [1, 2, 3, 4, 5]
if let index = findIndex(of: 3, in: numbers) {
    print("Index of 3 in numbers is \(index)") // 输出 "Index of 3 in numbers is 2"
}

如果要为泛型添加多个约束,可以使用 where 关键字:

func someFunction<T, U>(param1: T, param2: U) where T: Equatable, U: Comparable {  
    // 在这个函数中,T 需要遵循 Equatable 协议,U 需要遵循 Comparable 协议  
}

关联类型 #

协议可以有一个或多个关联类型作为其定义的一部分。关联类型是在协议内部定义的占位符名称,表示协议中使用到的某种类型,直到被采纳协议的类型具体化。例如:

protocol Container {
    associatedtype ItemType
    mutating func append(_ item: ItemType)
    var count: Int { get }
    subscript(i: Int) -> ItemType { get }
}

struct IntStack: Container {
    // existing implementation of IntStack
    var items = [Int]()
    mutating func push(_ item: Int) {
        items.append(item)
    }
    mutating func pop() -> Int {
        return items.removeLast()
    }

    // conformance to the Container protocol
    typealias ItemType = Int

    mutating func append(_ item: Int) {
        self.push(item)
    }

    var count: Int {
        return items.count
    }

    subscript(i: Int) -> Int {
        return items[i]
    }
}

总结 #

Swift 的泛型提供了一种强大且灵活的方式来编写可重用和类型安全的代码。通过泛型,你可以定义独立于任何具体类型的函数、方法、类、结构体和枚举,并在需要时进行类型约束,以确保代码的准确性和健壮性。理解和掌握泛型是编写高效、通用、高度可重用代码的关键。

本文共 949 字,上次修改于 Dec 16, 2024