Objective-C 协议(protocol)

协议(protocol)是Objective-c中一个很是重要的语言特性,从概念上讲,很是相似于JAVA中接口. 一个协议其实就是一系列有关联的方法的集合(为方便后面叙述,咱们把这个协议命名为myProtocol)。协议中的方法并非由协议自己去实现,相反而 是由遵循这个协议的其余类来实现。换句话说,协议myProtocol只是完成对协议函数的声明而并无论这些协议函数的具体实现。一般协议和delegate同时使用是一种很是好的设计模式。html

声明一个协议的语法很是简单:设计模式

  1. @protocol myProtocol <NSObject>  
  2. @required  
  3. -(void) protocolNameA:(NSString*)string;  
  4. @optional  
  5. -(void) protocolNameB:(NSString*)string;  
  6. @end  


第一行是声明这个协议的名字为myProtocol。尖括号中的NSObject自己也是一个协议,其中定义了不少基本的协议函数,好比 performSelector,isKindOfClass,respondsToSelector,conformsToProtocol,retain,release 等。app

协议接口分为required和optional两类。required顾名思义是说遵照这个协议的那个类“必需要”实现的接口,而optional则是能够实现也能够不实现的。协议接口的定义和普通的函数定义是同样的。框架

最后一行@end表示协议定义结束。这个协议的定义一般是在.h文件中。函数


定义一个类遵循这个协议:测试

  1. @interface myClass  <myProtocol>  
  2. @interface myClass :NSObject<myProtocol>  
  3. @interface myClass :NSObject<myProtocol, NSCoding>  

上 面分别是三种不一样的状况。编译的时候编译器会自动检查myClass是否实现了myProtocol中的必要的(@required)接口。若是没有实现 则会发出一个警告信息。另外须要注意的是,若是有继承自myClass的子类,这些子类也是会自动遵循myClass所遵循的协议的,并且也能够重载这些 接口。ui


为何须要协议?spa

苹果的官方文档指出三个缘由:.net

  • To declare methods that others are expected to implement设计

  • To declare the interface to an object while concealing its class

  • To capture similarities among classes that are not hierarchically related

    其实还有第四个很重要的缘由,那就是减小继承类的复杂性。一个经典的例子就是iOS UI框架里面的UITableViewController类。假如没有“协议”功能,用户就必须选择用继承和重载接口的方法来实现复杂的UI控制以及其 他事件的处理——这就对基类的设计提出了更大的挑战了。对于像这样一个table view,一个很好的实现方法就是采用协议,由协议里的接口来控制不一样的数据源以及各类复杂的用户操做。UIKit中设计了两个很好的协议 UITableViewDelegate,UITableViewDataSource来实现UITableViewController的控制。任何遵 循这两个协议的类均可以实现对UITableView的控制。


    关于 id类型的运用:(不喜欢钻牛角尖的朋友,能够略过这一部分)

    id 类型在iOS中是一个通用类型,有点相似C语言的void*类型。编译器不能检查到定义为id类型的变量的实际类型,id类型的识别是发生在运行时阶段。 可是咱们能够用 id<protocol_name> obj;这样的语法形式在编译阶段就可让编译器知道obj只能够发送protocol_name中的消息,若是所发送的消息不在 protocol_name中,编译器会给一个警告信息“Instance method 'xxxx:' not found......”。这种状况多用于代理模式的实现,好比某一个类有一个delegate 的property:

     

    1. id <myProtocol> delegate;  

    这样,在编译阶段咱们就能够知道用delegate所发送的消息是否是在它所遵循的myProtocol中的消息。好了, 到这里笔者钻起了牛角尖,我把id后面的 <myProtocol>删掉,而后用delegate发送一个并不存在于myProtocol中的消息,结果编译器仍是给了“Instance method 'xxxx:' not found......”的警告信息。更奇怪的是,当发送一个存在于myProtocol中的消息时,编译器居然没有这样的警告信息。这两个测试并不能说 明以前的解释是错误的,姑且认为id<myProtocol> delegate这种写法是为了便于知道这个delegate遵循了myProtocol的协议吧。
相关文章
相关标签/搜索