泛型是 Swift 中一种强大的编程特性,它可以让你编写更加灵活、可重用的代码。泛型可以用于函数、结构体、枚举和类。以下是 Swift 中泛型的一些用法总结:

  1. 泛型函数:泛型函数可以用于处理不同类型的数据,而不需要为每种类型编写单独的函数。泛型函数使用尖括号(<>)来定义类型参数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    func swapValues<T>(_ a: inout T, _ b: inout T) {
    let temp = a
    a = b
    b = temp
    }

    var a = 1
    var b = 2
    swapValues(&a, &b)

    print("a: \(a), b: \(b)") // a: 2, b: 1
  2. 泛型类型:泛型类型让你可以定义灵活的、可重用的组件,如结构体、枚举和类。和泛型函数一样,泛型类型使用尖括号(<>)来定义类型参数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    struct Stack<Element> {
    private var items: [Element] = []

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

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

    // 使用
    var intStack = Stack<Int>()
    intStack.push(1)
    intStack.push(2)
    print(intStack.pop()!) // 2
  3. 类型约束:类型约束用于限制泛型类型参数必须遵循的特定协议或继承自特定类。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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 index = findIndex(of: "Swift", in: ["Objective-C", "Swift", "Kotlin"])
    print(index!) // 1
  4. 关联类型:关联类型是在协议中定义的占位类型,它在协议被实现时才被指定为具体类型。关联类型使用 associatedtype 关键字声明。需要注意的是如果一个协议有泛型关联值,是不允许直接用来声明对象的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    protocol Container {
    associatedtype Item
    mutating func append(_ item: Item)
    var count: Int { get }
    subscript(i: Int) -> Item { get }
    }

    struct IntArrayContainer: Container {
    typealias Item = Int
    private var items: [Int] = []

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

    var count: Int {
    return items.count
    }

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

    或者

    struct ArrayContainer<T>: Container {
    private var items: [T] = []

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

    var count: Int {
    return items.count
    }

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

    泛型类(以及泛型结构体、泛型枚举和泛型函数)是在编译时确定具体类型。泛型的主要目的是编写可重用和类型安全的代码,而不是在运行时动态地确定类型。编译泛型类时编译器会根据提供的具体类型生成特定的代码。它会检查泛型代码的类型参数和类型约束,以确保代码的正确性。然后,在实例化泛型类或调用泛型函数时,编译器会根据具体的类型参数生成特定的代码。这个过程被称为“特化”(specialization)。