本篇要讨论的是协议和继承之间的关系,但为了方便理解,先从协议(Protocol)、委托(Delegate)和类别(Category)的关系说起。我曾经跟很多面试者问过这个问题,这几个概念之间的区别与联系,但是能完整答出来的很少。这几个概念在Objective-C里面是很基础,也是很重要的,用的好的话能大大提高代码的灵活性。
Delegate相信大家不会感到陌生,从学习iOS 开发界面的第一节课起,就接触过UITableViewDelegate ,到后来自己写Delegate用来在View和ViewController之间传递消息。Category也是用的比较多,最典型的就是用来添加 UIView设置top、bottom、left、right这些属性的方法,稍微深入一点的会了解到Category不仅可以添加方法,还可以通过runtime添加属性。而Protocol 了解的人就比较少了,仅仅只是知道Delegate里面用到了Protocol,却说不出他们之间有什么关系。下面我重点说说协议。
其实从广义上来说, Delegate和Category都是一种Protocol,在苹果的官方文档中是这样说的,类接口是与类相关的方法和属性的集合,而协议就是约定这些方法和属性的,他不依赖于特定的类。从这个定义上来看,包含了几个要素:
1. 协议是一种接口,或者说一种约定,必须被类实现才有意义。
2. 任何类都有可能实现这个协议。
3. 协议中包含一些方法或属性。
这跟C++里面的抽象类或者Java里面的Interface有点像,事实上,我们也确实可以这么理解,只不过,Objective-C里面没有抽象类,而且也不能像C++那样继承多个类,所以才有了协议这么一说。
协议分为正式协议和非正式协议,正式协议包含必选和可选的方法,而非正式协议都是必选的,如果不实现,编译器就会报错。Category就是一种非正式协议,他是在当前类的基础上实现的协议,不能给其他类使用,协议的内容就是Category里面定义的方法。而Delegate是不同类之间的(正式)协议,通过一个id<XXXDelegate>来传递消息。 这里的id是任何Objective-C的类型,Delegate与Protocol的区别在于Protocol是可以申明类方法的,而Delegate只能是实例方法。
由此可见,协议是很灵活的,他并不限定谁去实现它,它只关心协议有没有被正确地实现。这种松散的关系正好适合于降低类之间的耦合性,也可以将一些不必要的信息隐藏起来。
比如我们有一个类,叫VCManager,用于统一处理一系列ViewController的创建及相关属性的赋值。由于程序中的ViewController是多种多样的,我们可以在VCManager中把所有的类都包含进来,但这样会导致头文件依赖过多,不利于维护。要想解决依赖的问题,可以通过协议或者类继承的方式来处理。类继承的方式容易理解,就是父类封装一个创建ViewController的接口,子类负责具体的实现,这种方式我们叫做抽象工厂模式。 而协议的处理方式就是让这些ViewController都实现同一个协议,这个协议我们姑且称作VCManagerProtocol,然后VCManager中通过调用id<VCManagerProtocol> 的协议方法,来实现ViewController的创建和属性的赋值。
如果你仔细比较这两种实现的方式,会发现类继承要写的代码比较少,但多抽了一层,不利于代码的扩展,而协议要写的代码比较多(每个类都得实现协议方法),但不会增加类的层级,以后维护起来更方便。
我前面也提到了,协议可以认为是C++里面的抽象类,也就是说这些ViewController相当于是继承了VCManagerProtocol这个“抽象”的类,从这个角度来看协议也是一种继承。只是比一般的继承更灵活。
网友评论