内容简介:通用代码使您能够根据您定义的要求编写可以使用任何类型的灵活,可重用的函数和类型。您可以编写避免重复的代码,并以清晰,抽象的方式表达其意图。泛型是Swift最强大的功能之一,Swift标准库的大部分内容都是使用通用代码构建的。真是烧脑的玩意......
通用代码使您能够根据您定义的要求编写可以使用任何类型的灵活,可重用的函数和类型。您可以编写避免重复的代码,并以清晰,抽象的方式表达其意图。
泛型是Swift最强大的功能之一,Swift标准库的大部分内容都是使用通用代码构建的。
import Foundation //泛型函数 func swapTwoValues<T>(_ a: inout T, _ b: inout T) { let tmp = a a = b b = tmp } var a = 1, b = 2 print("\(a)====\(b)") swapTwoValues(&a, &b) print("\(a)====\(b)") //泛型类型(泛型类,泛型结构体,泛型枚举),听起来挺高大上,其实就是给自定义类加个泛型 struct Stack<Element> { var items: [Element] = [] mutating func push(_ item: Element) { items.append(item) } mutating func pop() -> Element { return items.removeLast() } } //扩展泛型类型 extension Stack { var topItem: Element? { return items.isEmpty ? nil : items[items.count - 1] } } var strings = Stack<String>() strings.push("hello") print(strings.topItem) print(strings.pop()) //泛型约束(不限于泛型类型,除了泛型类型就是TM的泛型函数) //泛型约束不能省略,如果省略value == v就不能运行了,没法玩了. //泛型约束必须是特定类继承,或符合特定协议或协议组合 //这里Equable不能被替换为String,因为String是结构体,不能被继承.Int, Bool, Double, anything else... //返回值不能用泛型, because the type to use for T is inferred from the types of values passed to the function. // (因为类型都是从传递给函数的值的类型推断出来的),除非再传一个参数,类似: // func findIndex1<T: Equatable, S: SignedInteger>(of value: T,in array: [T], _ type: S) -> S? // 告诉一下Swift,接下来会发生什么,不然Swift心里会发慌... func findIndex1<T: Equatable>(of value: T,in array: [T]) -> Int? { for (i, v) in array.enumerated() { if value == v { return i } } return nil } let arr = ["a", "b", "c", "d", "e"] let index = findIndex1(of: "a", in: arr) print(index) //关联类型 //协议中的泛型,实现具体类型的时候,由自己指定泛型类型为某种具体类型. protocol Container { associatedtype Item mutating func append(_ item: Item) var count: Int { get } subscript(i: Int) -> Item { get } } //这里typealias item不能等于协议,例如typealias Item = Equatable //这样Swift就不知道`EquableStack`应该怎么分配内存了有木有...,谁TM知道`EquableStack`实现了几个协议 //脚踏了几只船? //typealias Item = Int删掉也可以,可以通过append,推断出Item类型 struct IntStack: Container { mutating func push(_ item: Item) { items.append(item) } mutating func pop() -> Item { return items.removeLast() } typealias Item = Int var items: [Item] = [] mutating func append(_ item: Item) { items.append(item) } var count: Int { return items.count } subscript(i: Int) -> Item { return items[i] } } //上面的Stack可以写作下面方式 //因为通过append可以知道Element为Item的具体类型,所以typealias可以省略 //又因为Stack1是泛型类型,Element创建实例对象时具体指出,所以,一下代码完全正确. //可以写typealias Item = Element, 然后Element跟Item可以互相交叉替换 struct Stack1<Element>: Container { var items = [Element]() mutating func push(_ item: Element) { items.append(item) } mutating func pop() -> Element { return items.removeLast() } //conformance to the Container mutating func append(_ item: Element) { push(item) } var count: Int { return items.count } subscript(i: Int) -> Element { return items[i] } } var strings1 = Stack1<String>() strings.push("hello") print(strings.topItem) print(strings.pop()) //扩展现有类型以指定关联类型 //array 中有append用来推断具体类型,并且有count,有下标 //所以以后完全可以使用Array作为Container //但是typealias Container = Array也是不错的 extension Array: Container {} //将约束添加到关联类型 //如果这样定义,得像下面这样搞 //struct Stack1<Element: Equatable>: Container protocol Container1 { associatedtype Item: Equatable mutating func append(_ item: Item) var count: Int { get } subscript(i: Int) -> Item { get } } //在关联类型的约束中使用协议 //这个JB关系有点乱,有木有... //儿子有一个家,爹有一个家,儿子从爹那继承过来的家跟自己成立的家必须是一个家,不能搞分家... //大概就是这样了.... protocol SuffixableContainer: Container { associatedtype Suffix: SuffixableContainer where Suffix.Item == Item func suffix(_ size: Int) -> Suffix } extension Stack1: SuffixableContainer { func suffix(_ size: Int) -> Stack1 { var result = Stack1() //max是用来防止程序崩溃的, for index in max((count-size), 0)..<count { result.append(self[index]) } return result } // Inferred that Suffix is Stack. } var stackOfInts = Stack1<Int>() stackOfInts.append(10) stackOfInts.append(20) stackOfInts.append(30) let suffix = stackOfInts.suffix(3) //Generic Where Clauses(通用条款) //泛型条件约束吧... where func allItemsMatch<C1: Container, C2: Container>(_ someContainer: C1, _ anotherContainer: C2) -> Bool where C1.Item == C2.Item, C1.Item: Equatable { // Check that both containers contain the same number of items. if someContainer.count != anotherContainer.count { return false } // Check each pair of items to see if they're equivalent. for i in 0..<someContainer.count { if someContainer[i] != anotherContainer[i] { return false } } // All items match, so return true. return true } var stackOfStrings = Stack1<String>() stackOfStrings.push("uno") stackOfStrings.push("dos") stackOfStrings.push("tres") var arrayOfStrings = ["uno", "dos", "tres"] if allItemsMatch(stackOfStrings, arrayOfStrings) { print("All items match.") } else { print("Not all items match.") } extension Stack1 where Element: Equatable { func isTop(_ item: Element) -> Bool { guard let last = items.last else { return false } return item == last } } //如果将没有遵守Equatable用于该方法,会报错 if stackOfStrings.isTop("tres") { print("Top element is tres.") } else { print("Top element is something else.") } //上面where扩展类型,下面where扩展协议,这TM就比较6了... extension Container where Item: Equatable { func startsWith(_ item: Item) -> Bool { return count >= 1 && self[0] == item } } if [9, 9, 9].startsWith(42) { print("Starts with 42.") } else { print("Starts with something else.") } //Item是特定类型的where子句 extension Container where Item == Double { func average() -> Double { var sum = 0.0 for index in 0..<count { sum += self[index] } return sum / Double(count) } } print([1260.0, 1200.0, 98.6, 37.0].average()) //关联类型和泛型子句 protocol Container2 { associatedtype Item mutating func append(_ item: Item) var count: Int { get } subscript(i: Int) -> Item { get } associatedtype Iterator: IteratorProtocol where Iterator.Element == Item func makeIterator() -> Iterator } protocol ComparableContainer: Container2 where Item: Comparable {} //泛型下标 extension Container2 { subscript<Indices: Sequence>(indices: Indices) -> [Item] where Indices.Iterator.Element == Int { var result = [Item]() for index in indices { result.append(self[index]) } return result } }
真是烧脑的玩意......
--EOF--
以上所述就是小编给大家介绍的《Generics》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Generics
- Generics for Go
- 小结Swift文档-Generics
- Shipping Const Generics in 2020
- The Next Step for Generics
- TypeScript Generics. Discussing naming conventions
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。