
泛型
泛型概念
泛型代表某种指定的类型
泛型是 Swift 中最强大的特性之一,大量的 Swift 标准库使用了泛型,比如数组和字典都是泛型集合。
泛型能让你写出支持任意类型的灵活的、可复用的函数,它能将类型参数化,提高代码复用率,减少代码量。
泛型定义
- 泛型可以定义在函数、类、结构体、枚举后
- 泛型名称以逗号分隔,并用尖括号包裹起来
- 泛型可以在当前作用域内或扩展中使用
泛型示例
泛型在函数中使用时,可以自动推断类型
func swap<T>(_ a: inout T, _ b: inout T) {(a, b) = (b, a)}
var x = 10, y = 20print(x, y) // 10 20swap(&x, &y)print(x, y) // 20 10
泛型在类、结构体、枚举中使用时,需要在实例初始化时就指定好类型
struct Stack<Element> {var items = [Element]()mutating func push(_ item: Element) {items.append(item)}mutating func pop() -> Element {return items.removeLast()}func description() {print(items)}}
var stack1 = Stack<String>()stack1.push("apple")stack1.push("orange")stack1.description()var stack2 = Stack<Int>()stack2.push(1)stack2.push(2)stack2.description()
关联类型
- 关联类型与泛型的用途、用法类似
- 关联类型只能用于协议,而泛型不能在协议中使用
- 当某个类型遵守协议时,也需要给协议的关联类型指定实际类型
protocol CollectionProtocol {associatedtype ItemTypevar count: Int { get }subscript(i: Int) -> ItemType { get }mutating func append(_ item: ItemType)}
struct Stack<Element>: CollectionProtocol {/**Generics / `String` / `Int` ...*/typealias ItemType = Elementvar items = [Element]()mutating func push(_ item: Element) {items.append(item)}mutating func pop() -> Element {return items.removeLast()}// MARK: - ContainerProtocolvar count: Int {return items.count}subscript(i: Int) -> Element {return items[i]}mutating func append(_ item: Element) {self.push(item)}}
类型约束
类型约束是指类型必须继承自特定的类或遵循特定的协议。举例:
func test<T: Equatable & Comparable>(a: T, b: T) -> Bool {return false}
func index<T: Equatable>(of valueToFind: T, in array:[T]) -> Int? {for (index, value) in array.enumerated() {if value == valueToFind {return index}}return nil}extension Array where Element: Equatable {func index(of valueToFind: Element) -> Int? {for (index, value) in self.enumerated() {if value == valueToFind {return index}}return nil}}
条件约束
where 语句可以对类型进行约束、对类型之间的等价关系进行约束,以及其他条件约束。
protocol CollectionProtocol {associatedtype ItemType// associatedtype ItemType: Equatablevar count: Int { get }subscript(i: Int) -> ItemType { get }mutating func append(_ item: ItemType)}
struct Stack<Element>: CollectionProtocol {/**Generics / `String` / `Int` ...*/typealias ItemType = Elementvar items = [Element]()mutating func push(_ item: Element) {items.append(item)}mutating func pop() -> Element {return items.removeLast()}// MARK: - ContainerProtocolvar count: Int {return items.count}subscript(i: Int) -> Element {return items[i]}mutating func append(_ item: Element) {self.push(item)}}
extension Array: CollectionProtocol{}
func allItemsMatch<C1: CollectionProtocol, C2: CollectionProtocol>(_ collection1: C1, _ collection2: C2) -> Boolwhere C1.ItemType == C2.ItemType, C1.ItemType: Equatable{if collection1.count != collection2.count {return false}for i in 0..<collection1.count {if collection1[i] != collection2[i] {return false}}return true}
var tos = Stack<String>()tos.push("google")tos.push("runoob")tos.push("taobao")var aos = ["google", "runoob", "taobao"]if allItemsMatch(tos, aos) {print("匹配所有元素")} else {print("元素不匹配")}
[备注]:参考
