- 泛型。参数类型不同功能相同的函数有时需定义多个,造成重复,泛型用于解决这种情况。Dictionary和Array是最基本的两个。例如下面一个可以同时交换Int类型、string类型等多个类型的泛型函数
<>内定义占位类型T,并声明传入类型是T类型,T类型的具体类型在调用该函数时由传参推断//Generaic Functions func swapTwoValues<T>(_ a: inout T, _ b: inout T) { let temporatyA = a a = b b = temporatyA }
- 系统中使用了一些默认的类型名,例如字典中的Key、Value,数组中的Element,而我们定义的时候通常用T、U、V
- 泛型类型实例
struct Stack<Element> { var items = [Element]() mutating func push(_ item: Element) { items.append(item) } mutating func pop() -> Int{ return items.removeLast() } } var stackOfStrings = Stack<String>() stackOfStrings.push("uno") stackOfStrings.push("dos") stackOfStrings.push("tres") stackOfStrings.push("cuatro") let fromTheTop = stackOfStrings.pop()
- 使用extension对泛型类型进行扩展,使用类型参数不用重新定义可以直接使用原参数类型
extension Stack { var topItem: Element? { return items.isEmpty ? nil : items[items.count - 1] } }
- 类型约束。有时对于泛型函数和泛型类的使用范围有约束,我们可以指定某些类的子类或者遵循某些协议方可适用。例如字典中key被约束为只有遵循hashable才可以,(such as String, Int, Double, and Bool)
- 语法
func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) { //function body goes here }
- 实例
只有遵循Equatable协议的类才可以使用==符号,如果不声明T为Equatable类型,则可能存在不能使用==符号比较的类,会报错func findIndex<T: Equatable>(of valueToFind: T, in array: [T]) -> Int? { for (index, value) in array.enumerated() { if value == valueToFind { return index } } return nil }
- 使用associatedtype在协议中定义关联类型,使用typealias在遵循协议的实现中指定关联类型的具体类型,同时在associatedtype后可以使用冒号进行关联类型限制,如下
protocol Container { associatedtype Item: Equatable mutating func append(_ item: Item) var count: Int { get } subscript(i: Int) -> Item { get } }
- 使用
struct IntStack: Container { // original IntStack implementation var items = [Int]() mutating func push(_ item: Int) { items.append(item) } mutating func pop() -> Int { return items.removeLast() } // conformance to the Container protocol typealias Item = Int mutating func append(_ item: Int) { self.push(item) } var count: Int { return items.count } subscript(i: Int) -> Int { return items[i] } }
- 对于已经实现某协议的类可以使用extension加空实现体来进行声明
extension Array: Container {}
- 使用where在函数声明中增加限制,如果不满足则函数不会被调用且会报错
该函数实现了对不同类型(array和stack),但其中item相同的类型进行比较
上述代码中包括四个限制func allItemsMatch<C1: Container, C2: Container>(_ someContainer: C1, _ anotherContainer: C2) -> Bool where C1.Item == C2.Item, C1.Item: Equatable{ if someContainer.count != anotherContainer.count { return false } for i in 0..<someContainer.count { if someContainer[i] != anotherContainer[i] { return false } } return true }
1.C1遵循Container协议(C1: Container)
2.C2遵循Container协议 (C2: Container)
3.C1、C2的Item类型一致(C1.Item == C2.Item)
4.C1、C2的Item遵循Equatable协议,即可用==比较(C1.Item: Equatable) - 使用where语句在扩展的时候增加限制。如果不增加Equatable的限制会报错:Element不一定能使用==进行判断
使用guard进行判断,不存在时直接返回假//Extension with a Generic Where Clause extension Stack where Element: Equatable { func isTop(_ item: Element) -> Bool { guard let topItem = items.last else { return false } return topItem == item } }
- 泛型脚本
传入类型参数名为Indices遵循Sequence协议,且其中的每个元素都为Int类型extension Container { subscript<Indices: Sequence>(indices: Indices) -> [Item] where Indices.Iterator.Element == Int { var result = [Item]() for index in indices { result.append(self[index]) } return result } }
实现传入index数组,传入array中Item数组var stackOfInts = Stack<Int>() stackOfInts.push(1) stackOfInts.push(2) stackOfInts.push(3) stackOfInts.push(4) var aArray = [0,3] print(stackOfInts[aArray])
Generics
最后编辑于 :
©著作权归作者所有,转载或内容合作请联系作者
- 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
- 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
- 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
推荐阅读更多精彩内容
- 文章来源 参考:http://www.cnblogs.com/xdp-gacl/p/4321012.html 一、...