- 之前在文章Swift基础语法(三)中有介绍过泛型,本文是对之前介绍的补充。
定义泛型函数:
代码语言:javascript复制func swapTwoValues<T>(_ a: inout T, _ b: inout T) { let temporatyA = a a = b b = temporatyA}
定义泛型类型:
代码语言:javascript复制struct Stack<Element> { var elements = [Element]() mutating func push(_ element: Element) { elements.append(element) } mutating func pop() -> Element { return elements.removeLast() }}
外界使用push如下:
代码语言:javascript复制var stackOfString = Stack<String>()stackOfString.push("uno")stackOfString.push("dos")stackOfString.push("tres")stackOfString.push("custro")
图解如下:
在上面基础上,外界使用pop如下:
代码语言:javascript复制var stackOfString = Stack<String>()stackOfString.pop()
图解如下:
扩展泛型类型
当你扩展一个泛型类型的时候,不需要在扩展的定义中提供类型形式参数列表。原始类型定义的类型形式参数列表在扩展体里面仍然有效,并且原始类型形式参数列表名称也用于扩展类型形式参数。
struct Stack<Element> { var elements = [Element]() mutating func push(_ element: Element) { elements.append(element) } mutating func pop() -> Element { return elements.removeLast() }}
extension Stack { var topItem: Element? { return elements.last }}
Where子句
泛型函数中使用where语句
代码语言:javascript复制protocol Container { associatedtype ItemType mutating func append(_ item: ItemType) var count: Int { get } subscript(i: Int) -> ItemType { get }}
func allItemsMatch<C1: Container, C2: Container>(someContainer: C1, anotherContainer: C2) -> Bool where C1.ItemType == C2.ItemType, C1.ItemType: Equatable { // 首先检查元素个数是否相等 if someContainer.count != anotherContainer.count { return false } // 然后检查每一个元素是否相等 for i in 0..<someContainer.count { if someContainer[i] != anotherContainer[i] { return false } } // 当所有都匹配成功后,返回ture return true}
该例中的约束如下:
- C1: Container 表示C1必须遵循Container协议
- C2: Container 表示C2必须遵循Container协议
- C1.ItemType == C2.ItemType 表示C1的ItemType必须要跟C2的ItemType相同
- C1.ItemType: Equatable 表示C1的ItemType必须要遵循Equatable协议
上面?这四点意味着下面?这四点:
- someContainer 是一个C1类型的容器
- anotherContainer 是一个C2类型的容器
- someContainer和anotherContainer中的元素类型是相同的
- someContainer中的元素可以通过(!=)操作符来检查他们是否不一样
泛型类型中使用where语句
可以在扩展中使用泛型的where子句
struct Stack<Element> { var elements = [Element]() mutating func push(_ element: Element) { elements.append(element) } mutating func pop() -> Element { return elements.removeLast() }}
extension Stack where Element: Equatable { func isTop(item: Element) -> Bool { guard let lastItem = elements.last else { return false } return item == lastItem }}
这里的where语句表示的是:只有当Stack中的元素类型是遵循Equatable协议的时候,才会添加isTop方法。
泛型下标
在Swift中,下标也是支持泛型的。你可以在subscript后面用尖括号来写类型占位符,你还可以在下标代码块花括号前写泛型where分句。
protocol Container { associatedtype ItemType mutating func append(_ item: ItemType) var count: Int { get } subscript(i: Int) -> ItemType { get }}
extension Container { subscript<Indices: Sequence>(indices: Indices) -> [ItemType] where Indices.Iterator.Element == Int { var result = [ItemType]() for index in indices { result.append(self[index]) } return result }}
- 尖括号中定义了泛型Indices,而Indices是遵循标准库中Sequence协议的某类型。
- 下标接收单个形参indices。其类型是Indices。
- 泛型where分句要求序列的遍历器必须遍历Int类型的元素,这就保证了序列中的元素类型与容器索引的类型是相同的
- 这些限定合在一起,就意味着传入的indices形式参数是一个整数的序列
以上。