泛型
泛型代码可根据自定义需求,写出适用于任何类型、灵活且可重用的函数和类型,避免重复的代码,用一种清晰和抽象的思维表达代码的意思
1.泛型用途
- //普通的函数,用来交换两个值
- funcswapTwoInts(inouta:Int,inoutb:Int){
- lettemporaryA=a
- a=b
- b=temporaryA
- }
- varsomeInt=3
- varanotherInt=107
- swapTwoInts(&someInt,&anotherInt)
- println("someIntisnow\(someInt),andanotherIntisnow\(anotherInt)")
- //prints"someIntisnow107,andanotherIntisnow3"
- funcswapTwoStrings(inouta:String,0); background-color:inherit">b:String){
- funcswapTwoDoubles(inouta:Double,0); background-color:inherit">b:Double){
- }
2.泛型函数
占位符T是一种类型参数的示例,类型参数指定命名为一个占位类型,并且紧随在函数名后面,使用一对尖括号括起来,一旦类型参数被确定,就可以用来定义函数的参数类型(a,b),或作为函数的返回类型,或作为函数主题的注释类型,此时类型参数所代表的占位符不管函数任何时候被调用,都会被实际类型所替代copy
funcswapTwoValues<T>(inouta:T,0); background-color:inherit">b:T){
lettemporaryA=a
a=b
b=temporaryA
}
泛型版本的函数使用占位符(T)来替代实际类型名,占位符并没有提示T必须是什么类型,但a和b必须是用一种类型,在swapTwoValues被调用时才能确定T所表示的类型
copy
funcswapTwoInts(inoutb:Int)
funcswapTwoValues<T>(inoutb:T)
swapTwoValues(&someInt,0); background-color:inherit">//someIntisnow107,andanotherIntisnow3
varsomeString="hello"
varanotherString="world"
swapTwoValues(&someString,&anotherString)
//someStringisnow"world",andanotherStringisnow"hello"
3.泛型类型
Swift允许自定义泛型类型,这些自定义类、结构体和枚举作用于任何类型copy
//以下是一个用泛型写的栈Stack,模拟栈的push和pop
structIntStack{
varitems=Int[]()
mutatingfuncpush(item:Int){
items.append(item)
mutatingfuncpop()->Int{
returnitems.removeLast()
}
//Stack提供两个方法,push和pop,从栈中压进一个值和弹出一个值,但只能用于int值,下面定义一个泛型Stack类,可处理任何类型的栈
structStack<T>{
varitems=T[]()
mutatingfuncpush(item:T){
items.append(item)
mutatingfuncpop()->T{
returnitems.removeLast()
varstackOfStrings=Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")
stackOfStrings.push("cuatro")
//thestacknowcontains4strings
letfromTheTop=stackOfStrings.pop()
//fromTheTopisequalto"cuatro",andthestacknowcontains3strings
4.类型约束
有时候对使用在泛型函数和泛型类型上的类型强制约束为某种特定的类型是非常有用的,可以指定一个必须继承自指定类的类型参数,或者遵循一个特定的协议或协议构成4.1语法
copy
//假定函数有两个类型参数,类型参数T必须是SomeClass子类的类型约束,类型参数U必须遵循SomeProtocol协议的类型约束
funcsomeFunction<T:SomeClass,U:SomeProtocol>(someT:T,someU:U){
//functionbodygoeshere
}
4.2实例
非泛型函数,查找以给定的String数组,若找到匹配的字符串,返回下标copy
funcfindStringIndex(array:String[],0); background-color:inherit">valueToFind:String)->Int?{
for (index,value)inenumerate(array){
ifvalue==valueToFind{
returnindex
returnnil
letstrings=["cat","dog","llama","parakeet","terrapin"]
ifletfoundIndex=findStringIndex(strings,"llama"){
println("Theindexofllamais\(foundIndex)")
//prints"Theindexofllamais2"
//使用泛型实现相同功能,但是下面这个泛型函数不会被编译,在等式value==valueToFind里,不是所有的类型都可以用等式==来进行比较,如果是自己创建的自定义类型,Swfit就无法猜到这个等于的意思,所以编译下面代码的时候就会报错
funcfindIndex<T>(array:T[],0); background-color:inherit">valueToFind:T)->Int?{
}
Swift标准库定义了一个Equatable协议,要求任何遵循的类型实现等式 == 和不等式 != 对两个该类型进行比较。所有的Swift标准类型自动支持Equatable协议
5.关联类型
定义一个协议的时候,声明一个或多个关联类型作为协议定义的一部分是非常有用的,一个关联类型给定作用于协议部分的类型一个节点名。作用于关联类型上实际是不需要指定的,直到该协议接受。关联类型为 typealias关键字5.1实例
定义ItemType关联类型,1. append方法添加一个新的item 2. count方法获取数量 3. 通过索引值检索到每一个itemcopy
protocolContainer{
typealiasItemType
mutatingfuncappend(item:ItemType)
varcount:Int{get}
subscript(i:Int)->ItemType{get}
//IntStack的非泛型版本,实现Container协议的所有三个要求
structIntStack:Container{
//originalIntStackimplementation
//conformancetotheContainerprotocol
typealiasItemType=Int
mutatingfuncappend(item:Int){
self.push(item)
varcount:Int{
returnitems.count
subscript(i:Int)->Int{
returnitems[i]
//遵循Container协议的泛型版本
structStack<T>:Container{
//originalStack<T>implementation
//conformancetotheContainerprotocol
mutatingfuncappend(item:T){
subscript(i:Int)->T{
}
5.2扩展一个存在的类型为已指定关联类型
Swift中的Array已经提供了一个append方法,一个count属性和通过下标查找元素的功能,都已满足Container协议的要求,就意味着可以扩展Array去遵循Container协议,只要通过简单声明Array适用于该协议就可以了6.Where语句
where语句要求一个关联类型遵循一个特定的协议,或那个特定的类型参数和关联类型可以是相同的copy
//定义allItemsMatch的泛型函数检查两个Container单例是否包含相同顺序的相同元素,如果匹配返回ture,否则返回false
funcallItemsMatch<
C1:Container,0); background-color:inherit">C2:Container
whereC1.ItemType==C2.ItemType,C1.ItemType:Equatable>
(someContainer:C1,0); background-color:inherit">anotherContainer:C2)->Bool{
//checkthatbothcontainerscontainthesamenumberofitems
ifsomeContainer.count!=anotherContainer.count{
returnfalse
//checkeachpairofitemstoseeiftheyareequivalent
foriin0..someContainer.count{
ifsomeContainer[i]!=anotherContainer[i]{
//allitemsmatch,soreturntrue
true
varstackOfStrings=Stack<String>()
stackOfStrings.push("uno")
stackOfStrings.push("dos")
stackOfStrings.push("tres")
vararrayOfStrings=["uno","dos","tres"]
ifallItemsMatch(stackOfStrings,arrayOfStrings){
println("Allitemsmatch.")
}else{
println("Notallitemsmatch.")
//prints"Allitemsmatch."
FROM: http://blog.csdn.net/huangchentao/article/details/32718325