前言
在Objective-C中,protocol和继承区别还是蛮大的:
@interface TestClass : TestFatherClass <TestProtocol>@end
讲的是,一个类TestClass,是继承自类TestFatherClass的子类,并遵守TestProtocol协议。
在Swift中,就看不出来了:
class TestClass : TestFatherClass , TestProtocol { }
也就是说在swift中面相协议更加被看重了,面向对象编程思想的基础上,更加推荐面向协议编程的思想了。
协议是什么?
首先跳出编程,协议是什么?
场景描述:甲方乙方为了实现一个目标A,拟定了协议B,双方承诺共同遵守协议,协议B中提到,场景C的时候,遵守协议的人要做D这件事。
现在甲方遇到了场景C,在遵守协议的原则下,甲方做了D这件事,最终甲方的目标A实现了。
当然这是非常理想的状况。
那么iOS的协议是什么呢?
A protocol declares a programmatic interface that any class may choose to implement. Protocols make it possible for two classes distantly related by inheritance to communicate with each other to accomplish a certain goal. They thus offer an alternative to subclassing. Any class that can provide behavior useful to other classes may declare a programmatic interface for vending that behavior anonymously. Any other class may choose to adopt the protocol and implement one or more of its methods, thereby making use of the behavior. The class that declares a protocol is expected to call the methods in the protocol if they are implemented by the protocol adopter.
实际上是一样的:
甲方类和乙方类为了实现功能A,遵守了协议B,协议B中有方法D,是在场景C的情况下要做D这件事。
那么在场景C的时候,D方法被执行了,最终实现了功能A。
有点绕是不是?
用对象和协议实现同一个详细的场景(有点啰嗦,但是非常实际的例子)
举个更详细一点的例子:
有按钮A,对应:人类小明
现在要实现需求:点击按钮的时候,打印对应类的对应名字+“你好!”
umm...怎么实现呢?界面好说,刷刷刷就写好了A按钮。点击事件怎么写呢?首先考虑的应该是对象。
写一个类,是人类,属性有名字,方法有打招呼。小明是人类,名字是小明,实现方法打招呼:打印“{.名字}你好!”
ok,需求解决了,歇了口气,so easy!
第二天,需求改了:
有按钮A两个,对应:人类小明;人类小红,她的昵称是红红。
现在要实现需求:点击按钮的时候,打印对应类的对应名字+“你好!”,小明显示小明,小红显示红红。
****!产品经理拖出去枪毙!小明和红红是什么鬼?为什么不打印小红呢?算了,强压怒火,改改改:
人类这个类里添加属性:昵称,打招呼的时候添加判断,如果昵称不为空,显示昵称,如果昵称为空,显示名字
哼哼,难不倒我的,再次解决。
第三天,需求又变了:
有按钮A3个,对应:人类小明;人类小红,她的昵称是红红;小狗小花。
现在要实现需求:点击按钮的时候,打印对应类的对应名字+“你好!”,小明显示小明,小红显示红红,小狗显示小花。
********!给产品经理扎个娃娃,天天刺刺刺!不过饭碗不能丢,依然要实现它:
代码不能太难看,重构一下,动物类,属性:名字,方法:打招呼(打印“{.名字}你好!”),人类,继承自动物类(人也是动物嘛),属性多一个昵称,在打招呼方法添加判断,如果昵称是空,super,如果昵称不为空,打印“{.昵称}你好!”
写完之后就开始担心了,如果哪一天产品经理突发奇想添加个汽车按钮怎么办?撞死算了。他应该不会那么无情无耻无理取闹吧?
呵呵,偏偏第四天,产品经理告诉你,他就是这么无情无耻无理取闹,汽车不错,就加个汽车好了!
有按钮A4个,对应:人类小明;人类小红,她的昵称是红红;小狗小花;大众汽车,他的种类是高尔夫,型号是xyz123。
现在要实现需求:点击按钮的时候,打印对应类的对应名字+“你好!”,小明显示小明,小红显示红红,小狗显示小花,汽车显示高尔夫xyz123。
是不是觉得这样下去不是个事了?单纯面向对象开发似乎已经不足以快速实现需求了,每次更迭如果脱离现有的数据结构,就会有重构的必要,时间成本和调试成本大大增加,协议这个东西的作用体现出来了
协议:对它打招呼,有一个属性:称呼
点击事件打印:{遵守协议:对它打招呼的类的称呼}+“你好!”
人类,名字小明;人类,名字小红,昵称红红。
想要对他们打招呼只要让人类遵守协议:对它打招呼,然后赋值时候,顺便判断下,如果昵称不为空,就让称呼是昵称,如果昵称为空,就让称呼是名字。
ok,管他加小狗还是汽车呢,只要让它遵守协议:对它打招呼,把产品经理打招呼的时候要显示的称呼给“称呼”赋值,要来多少都没事了。
总结
你如果觉得你的产品经理没这么坑,我觉得你还是预防万一为好,我维护一个2年的产品,为了满足多变的需求,定制了无数协议,现在看起来真的很好维护。
对象继承的特点:实现起来容易,但是扩展和维护麻烦
协议的特点:实现起来要定制协议,可能有点麻烦,但是耦合性非常低,利于维护,扩展性很强。
能用协议的地方,还是多用吧