原创Blog,转载请注明出处
blog.csdn.net/hello_hwc
一 泛型的定义
和C++的类似,泛型定义了一种适用于任何类型的,可重用的代码,用一种抽象的方式来实现代码。Swift的Array和Dictionary都是用泛型来实现的,因为Array可以保存String类型的变量,也可以保存Int类型的。
举个例子
func swapTwoInts(inout a: Int, inout b: Int) { let temporaryA = a a=b b = temporaryA } func swapTwoStrings(inout a: String, inout b: String) { let temporaryA = a a=b b = temporaryA } func swapTwoDoubles(inout a: Double, inout b: Double) { let temporaryA = a a=b b = temporaryA }
这是同样的函数结构用来交换两种类型,但是不用泛型的话,我们不得不为每一种类型都定义出对应的函数。十分繁琐。
使用泛型之后,我们只需要这样去定义
func swapTwoValues<T>(inout a: T, inout b: T) { let temporaryA = a a=b b = temporaryA }
这里的T是占为类型,就是告诉编译器,这是个通用的类型,在实际运算的时候,会有具体的类型进行替换。占为类型可以作为参数,也可以作为返回值。当然也可以定义多个,例如<T1,T2>
注意:Swift是类型安全的语言,编译器会进行类型检查,如果类型不匹配会报错。
二 类型约束
在泛型定义中,类型约束十分重要。比如,定义一个泛型对一组数据进行排序,那么这组数据一定要能够比较(大于,等于,小于),如若不然,传入一组数据中既有Int,又有String,Int和String进行排序,明显没有一个合理的规则。
泛型的约束表示这种类型必须继承某个类,或者实现某些协议。
语法如下
func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) { // function body goes here }
然后,实现一个使用类型约束来定义泛型的例子。
f?????unc findIndex<T: Equatable>(array: T[], valueToFind: T) -> Int? { for (index, value) in enumerate(array) { if value == valueToFind { return index } } return nil }
这里,通过泛型来定义一个在数组中查找指定数据的函数,明显这个类型T要支持==运算符。Equatable就是系统提供的一种协议,遵循这种协议的类型都可以使用==运算符。
三 关联类型
在二中,我们使用了系统提供的Equatable,那么如何自定义类似的协议呢?
使用关联类型,语法是在协议中使用typealise关键字来定义关联类型。
举例
protocol Container { typealias ItemType mutating func append(item: ItemType) var count: Int { get } subscript(i: Int) -> ItemType { get } }
这里,定义一种关联类型,ItemType,对于协议来说,任何遵循这个协议的结构体必须实现两个方法(append,count)一个下标脚本。而ItemType的具体类型由遵循协议的类来决定。例如
struct IntStack: Container { // IntStack
四 Where语句
Where语句对关联类型进行了更进一步的约束。一个where语句可以让一个关联类型遵循某个特定的协议,也可以让特定的数据类型和关联类型的数据类型一致。
func allItemsMatch< C1: Container, C2: Container where C1.ItemType == C2.ItemType, C1.ItemType: Equatable> (someContainer: C1, anotherContainer: C2) -> Bool { 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协议
2.C2必须遵循Container协议
3.C1和C2的ItemType一致
4.C1的ItemType遵循Equatable协议