一 协议的定义
协议中可以声明属性,方法,初始化器,以及下标等。要注意所有的协议都不能声明析构器(协议不能生成实例,也不会有析构的必要)
二 实现协议
协议在实现过程中,必须要实现protocol中所有声明的属性、函数等。参数需保持一致。
在实现属性时,可以实现计算属性;也可以实现为存储属性。
这里要注意一点,在协议中定的“==”编译要求需要指定为static才让通过编译。在实现该函数时,“==”操作符重载均为全局函数。
三使用协议 swift3,0在参数传递中发生了些变化,在协议的使用中也有些许的变化发生。
3.1 mutating
该关键字用来修饰值类型的函数,表示该函数会修改值类型的值。同时协议中对应的该函数也需要声明为mutating。对类来说没有这条要求,协议中的mutating对类没有影响。那么在使用这一条时就注意,如果协议的可能会给让值类型来实现(struct,enum),那么就将需要改变属性的函数声明为mutating,不然编译器会报错
3.2关于函数传值与传引用
下面的代码 process(element:Shape)函数调用了 moveTo函数 ,而moveTo会让shape类型的属性发生改变。而我们知道的,swift传参均为传值,且默认声明为let类型(即不可变)。这时编译会报错
“cannot use mutating member on imutable value:’element’ is a ‘let’ constant’”
那按照课程中所述,在参数前声明var可行码? 如下也不可行编译器提示:“parameters may not have the var specifier”。显然swift3.0 已然不支持该参数说明。
总的来说3.0做了优化,因为本身来讲将函数参数声明为var在swift中是没有意义的!如果是引用参数,自然可以变化;但值类型参数的改变,并没有实际意义,不能改变函数外部,只能留在函数体类(将其作为返回值意义不大),有点类似与effective C++中条款,要求将函数参数类型全部设置为const。
在这里如果要改变值类型,这里做法是传引用,主动声明为inout。
“func process(element:inout Shape)“实际上在这里传进去的就为外部实例的指针,函数类对参数的改变,会影响到外面值。
同时进行了测试,这个函数传引用类型与值类型均能得到想要的结果。
不论该函数用于值类型还是引用类型,使用时均需使用修饰符 &
(这还真是与C++的引用一德性~~~)
3.3以上输出结果为:
四 检查协议类型
这里定义了一个AProtocol协议,一个Base类,Sub类继承了Base并实现了AProtocol协议
4.1运行时类型识别
用is标示符来进行运行时识别,返回一个boolean值。如下所示:item2 is AProtocol;该标示符是针对类型的识别item2 is Sub这样写也是没问题的。
编译时类型与运行时类型,在上面代码中var item1:Base,Base为item1的 编译时类型,而其运行时类型为Base。
那么在什么情况下需要进行类型识别呢?
试想:在多态调用的情况下,在一个list中存储编译类型为Base类的对象,但其运行时类型可能为Sub1,Sub2,………………SubN(这些类均为Base的子类),其中部分子类实现了ProtocolA。
遍历list,当发现对象是protocol协议的实现时,需要调用protocol协议中的某个函数。(这个时候需要进行下面介绍的强制转换)
这个时候就要需要用is来作判断了
4.2多态转型
前提:由上一段代码可知,item1,item2声明类型是Base类,item1内存中是Base,item2内存指向的是类,Sub实现了
当进行多态转型时
4.2.1可选类型
首先声明一个可选类型如下:var item3:AProtocol?这里为nil
进行转型时用as?如下:item3 = item1 as? AProtocol还是为nil
as?首先判断是否为AProtocol,如果为真 转化为”item1“的类型。
4.2强制转化
当确切的知道待转化类型时,可以用强制转换
首先声明一个类型var item4:AProtocol
并用as!如下:item4=item2 as! AProtocol 返回任然为item的类型
在进行强制转化时,如果item2不是AProtocol编译器会提示错误“Could not cast value of type ‘Base’ (0x1136b6448) to ‘AProtocol’ (0x114bc4200)
抓化完成后 item4调用sub的函数不需要用?号
五 更多的协议形式
5.1协议的继承
BProtcol:AProtocol协议支持继承,协议只能继承协议不能继承与类;其次实现子协议的的时候也鼻血实现父协议。
这里的继承更像时一次方法叠加,只是将B,A协议的方法加在一起了
5.2协议的组合
协议的组合在方法中func process(item:AProtocol & CProtocol)(这里的组合协议表示一个临时类型) 表示这里的item参数需要实现A与B两个协议。
var cb = ClassB() ;process(item: cb)
ClassB实现了b,c两个协议,而b又继承于A,所以可以调用
5.3可选协议
协议的某些成员可以定义为optional
在协议以及可选方法前都要加@objc(可选方法一定要加,非可选方法可加可不加)