10. Swift 泛型与关联类型.png

泛型

泛型概念

泛型代表某种指定的类型
泛型是 Swift 中最强大的特性之一,大量的 Swift 标准库使用了泛型,比如数组和字典都是泛型集合。
泛型能让你写出支持任意类型的灵活的、可复用的函数,它能将类型参数化,提高代码复用率,减少代码量。

泛型定义

  • 泛型可以定义在函数、类、结构体、枚举后
  • 泛型名称以逗号分隔,并用尖括号包裹起来
  • 泛型可以在当前作用域内或扩展中使用

泛型示例

泛型在函数中使用时,可以自动推断类型

  1. func swap<T>(_ a: inout T, _ b: inout T) {
  2. (a, b) = (b, a)
  3. }
  1. var x = 10, y = 20
  2. print(x, y) // 10 20
  3. swap(&x, &y)
  4. print(x, y) // 20 10

泛型在类、结构体、枚举中使用时,需要在实例初始化时就指定好类型

  1. struct Stack<Element> {
  2. var items = [Element]()
  3. mutating func push(_ item: Element) {
  4. items.append(item)
  5. }
  6. mutating func pop() -> Element {
  7. return items.removeLast()
  8. }
  9. func description() {
  10. print(items)
  11. }
  12. }
  1. var stack1 = Stack<String>()
  2. stack1.push("apple")
  3. stack1.push("orange")
  4. stack1.description()
  5. var stack2 = Stack<Int>()
  6. stack2.push(1)
  7. stack2.push(2)
  8. stack2.description()

关联类型

  • 关联类型与泛型的用途、用法类似
  • 关联类型只能用于协议,而泛型不能在协议中使用
  • 当某个类型遵守协议时,也需要给协议的关联类型指定实际类型
  1. protocol CollectionProtocol {
  2. associatedtype ItemType
  3. var count: Int { get }
  4. subscript(i: Int) -> ItemType { get }
  5. mutating func append(_ item: ItemType)
  6. }
  1. struct Stack<Element>: CollectionProtocol {
  2. /**
  3. Generics / `String` / `Int` ...
  4. */
  5. typealias ItemType = Element
  6. var items = [Element]()
  7. mutating func push(_ item: Element) {
  8. items.append(item)
  9. }
  10. mutating func pop() -> Element {
  11. return items.removeLast()
  12. }
  13. // MARK: - ContainerProtocol
  14. var count: Int {
  15. return items.count
  16. }
  17. subscript(i: Int) -> Element {
  18. return items[i]
  19. }
  20. mutating func append(_ item: Element) {
  21. self.push(item)
  22. }
  23. }

类型约束

类型约束是指类型必须继承自特定的类或遵循特定的协议。举例:

  1. func test<T: Equatable & Comparable>(a: T, b: T) -> Bool {
  2. return false
  3. }
  1. func index<T: Equatable>(of valueToFind: T, in array:[T]) -> Int? {
  2. for (index, value) in array.enumerated() {
  3. if value == valueToFind {
  4. return index
  5. }
  6. }
  7. return nil
  8. }
  9. extension Array where Element: Equatable {
  10. func index(of valueToFind: Element) -> Int? {
  11. for (index, value) in self.enumerated() {
  12. if value == valueToFind {
  13. return index
  14. }
  15. }
  16. return nil
  17. }
  18. }

条件约束

where 语句可以对类型进行约束、对类型之间的等价关系进行约束,以及其他条件约束。

  1. protocol CollectionProtocol {
  2. associatedtype ItemType
  3. // associatedtype ItemType: Equatable
  4. var count: Int { get }
  5. subscript(i: Int) -> ItemType { get }
  6. mutating func append(_ item: ItemType)
  7. }
  1. struct Stack<Element>: CollectionProtocol {
  2. /**
  3. Generics / `String` / `Int` ...
  4. */
  5. typealias ItemType = Element
  6. var items = [Element]()
  7. mutating func push(_ item: Element) {
  8. items.append(item)
  9. }
  10. mutating func pop() -> Element {
  11. return items.removeLast()
  12. }
  13. // MARK: - ContainerProtocol
  14. var count: Int {
  15. return items.count
  16. }
  17. subscript(i: Int) -> Element {
  18. return items[i]
  19. }
  20. mutating func append(_ item: Element) {
  21. self.push(item)
  22. }
  23. }
  1. extension Array: CollectionProtocol{}
  1. func allItemsMatch<C1: CollectionProtocol, C2: CollectionProtocol>
  2. (_ collection1: C1, _ collection2: C2) -> Bool
  3. where C1.ItemType == C2.ItemType, C1.ItemType: Equatable
  4. {
  5. if collection1.count != collection2.count {
  6. return false
  7. }
  8. for i in 0..<collection1.count {
  9. if collection1[i] != collection2[i] {
  10. return false
  11. }
  12. }
  13. return true
  14. }
  1. var tos = Stack<String>()
  2. tos.push("google")
  3. tos.push("runoob")
  4. tos.push("taobao")
  5. var aos = ["google", "runoob", "taobao"]
  6. if allItemsMatch(tos, aos) {
  7. print("匹配所有元素")
  8. } else {
  9. print("元素不匹配")
  10. }

[备注]:参考