每天学一点Swift----泛型(二)

四.类型约束

1.虽然程序可以对泛型形参传入任何类型,但有时候为泛型形参增加某种特定的约束也是必要的。就像字典,Dictionary的key的类型也是通过泛型形参来表示的,但Dictionary并不允许任意一种类型的数据都能作为key,只有实现了Hashable协议的类型才能作为key。这就是一种类型约束。

2.类型约束就是指定义类型参数时增加一个限制,约束这种类型参数必须继承指定的类,或遵守一个特定的协议或合成协议。

3.例如,定义了一个函数实现了对整数进行冒泡排序,当对Double,String类型进行比较是就需要到泛型了,但是又有另一个问题:能排序的数组元素必须是可比较大小的,否则程序无法对数组元素进行排序。也就是说,数组元素必须实现Comparable协议,这就需要使用类型约束了。

4.定义泛型时使用类型约束的语法格式如下:

<类型形参1:父类,类型形参2:协议,类型形参3:protocol<协议1,协议2>,...>

上面给出了3种形式的类型约束:

(1)类型形参1:实际传给该形参的类型必须继承指定父类

(2)类型形参2:实际传给该形参的类型必须遵守指定协议

(3)类型形参3:实际传给该形参的类型必须同时遵守合成协议的协议1,协议2

实际中具体需要定义多少个类型形参,完全取决于程序的需要。

5. Swift的String也遵守Comparable协议,因袭String也是可以比较大小的,Swift比较String的大小时按各字符对应的Unicode码进行比较。

五.关联类型

1.定义协议时,也允许定义一个或多个类型参数,这种类型参数本质上也属于泛型,但需要以关联类型(Associated Type)的形式进行声明。协议中的类型形参需要等到协议被实现时才会确定下来。

2.在协议中以typealias关键字来声明关联类型。

3.举个栗子:

protocol Container

{

//声明类型形参,该类型形参需要等到协议被实现时才能确定下来

typealias ItemType

//向容器中添加一个元素

mutating func append(item : ItemType)

//获取容器中元素的个数

var count : Int{}

//根据索引来获取元素

subscript(i : Int) -> ItemType {get}

}

上面程序中,正因为Container协议使用了类型形参,这个类型形参到底代表什么类型,必须等到实现该协议时才能确定下来,这使得该容器可以装任意类型的数据。这就要按实现者要指定什么类型了,例如:

struct IntList : Container

{

//显式指定ItemType类型代表Int类型

typealias ItemType = Int

...

}

4.我们已经知道,程序可以通过扩展让已有类型来遵守指定协议,包括使用空扩展让已有类型(该类型已经实现了协议的各种要求)遵守已有协议的情形。但没有涉及到泛型,实际上,这种用法完全是支持泛型的。例如:Swift的Array结构体已经提供了append(newEleme:T)方法,count属性,因此程序也可以通过扩展让Array实现Container协议:extension Array:Contaioner{}。这样Array结构体就实现了Container协议,因此Array也可以当成Container使用。

5.如果程序只需要简单地定义类型形参必须是某个类的子类,或者必须遵守某个协议,使用类型约束即可。如果程序需要对类型形参进行更多复杂的约束,就需要借助于where字句了。

6. where字句也属于泛型声明的一部分,where字句可以指定一个条件表达式,该条件表达式用于对类型形参增加更多额外的限制。在泛型声明中使用where字句的语法如下:

<类型形参:父类型,类型形参2:协议,... where条件>

7,举个栗子,下面将会定义一个copyContainer函数,这个函数用于将前一个Container中的元素复制到另一个Container中,此时就要求两个Container中的ItemType必须相等,另外,还加了Container容器包含的元素必须是可以打印的要求。

func copyContainer

where C1.ItemType == C2.ItemType, C1.ItemType : Printable>(src : C1, inout dest : C2)

{

let count = src.count

for var i=0; i

{

dest.append(sec[i])

}

}

上面代码中泛型声明一共有4个要求:

(1)C1类型形参必须遵守Container协议

(2)C2类型形参必须遵守Container协议

(3)C1的ItemType与C2的ItemType必须相同

(4)ItemType必须遵守Printable协议

你可能感兴趣的:(每天学一点Swift----泛型(二))