协议(protocol)是Objective-c中一个非常重要的语言特性,从概念上讲,非常类似于JAVA中接口. 一个协议其实就是一系列有关联的方法的集合(为方便后面叙述,我们把这个协议命名为myProtocol)。协议中的方法并不是由协议本身去实现,相反而是由遵循这个协议的其他类来实现。换句话说,协议myProtocol只是完成对协议函数的声明而并不管这些协议函数的具体实现。

声明一个协议的语法非常简单:

  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等。

协议接口分为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所遵循的协议的,而且也可以重载这些接口。

为什么需要协议?

苹果的官方文档指出三个原因:

    • 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的协议吧。

Objective-C 协议(protocol)的更多相关文章

  1. iOS阶段学习第19天笔记(协议-Protocol)

    iOS学习(OC语言)知识点整理 一.关于协议(Protocol)的介绍 1)概念:协议指多个对象之间协商的一个接口对象,协议提供了一些方法用在协议的实现者和代理者      之间通讯的一种方式 2) ...

  2. OC基础--分类(category) 和 协议(protocol)

    OC 中的category分类文件相当于 C#中的部分类:OC 中的protocol协议文件(本质是头文件)相当于 C#中的接口.今天就简单说明一下OC中的这两个文件. 由于视频中的Xcode版本低, ...

  3. 协议Protocol

    1.协议:是一组声明方法的集合,不能声明成员变量,作用类似于接口.           遵守此协议的类就相当于拥有了这个协议的所有方法的声明,如果父类遵守了某个协议,子类也遵守了这个协议.       ...

  4. 浅谈iOS开发的协议(protocol)和代理(delegate)

    协议和代理对于一个新手来说确实不讨好理解,也有很多的iOS开发的老手对此是懂非懂的.网上的很多博文只是讲了怎么使用,并没有说的很明白.下面我谈一下我的理解. 1.你要先搞明白,协议和代理为什么会出现, ...

  5. 关于ios object-c 类别-分类 category 的静态方法与私有变量,协议 protocol

    关于ios object-c 类别-分类 category 的静态方法与私有变量,协议 protocol 2014-02-18 19:57 315人阅读 评论(0) 收藏 举报 1.category, ...

  6. Objective-C中的协议(Protocol)和类别(Category)

    1.什么是协议? 2.协议与类别的声明和使用 1.什么是协议? 在Objective-C中,不支持多继承,即不允许一个类有多个父类,但是OC提供了类似的实现方法,也就是协议.协议有点类似于Java里的 ...

  7. Objective-C 中的协议(@protocol)和接口(@interface)的区别

    Objective-C 中的协议(@protocol),依照我的理解,就是C#, Java, Pascal等语言中的接口(Interface).协议本身不实现任何方法,只是声明方法,使用协议的类必须实 ...

  8. Objective-C:继承、分类(Category、extension)、协议(protocol),个人理解,仅供参考

    总结:继承.分类(Category.extension).协议(protocol)   一.继承: (1)特点: 继承多用于一般父类中的方法功能比较齐全,子类从父类继承过来使用,可以省略很多重复的代码 ...

  9. Objective-C:协议protocol

    六.协议(protocol) 关键字:@optional.@required (1)是一个类共享的一个方法列表 (2)它声明了一系列的方法而不进行实现 (3)遵从某个协议,就是需要实现协议中的方法 ( ...

  10. 协议(Protocol)与委托代理(Delegate)

    协议(Protocol)的作用: 1. 规范接口,用来定义一套公用的接口: 2. 约束或筛选对象. 代理(Delegate): 它本身是一种设计模式,委托一个对象<遵守协议>去做某件事情, ...

随机推荐

  1. sql server 判断日期当前月有多少天

    declare @tm datetime set @tm = CONVERT(datetime,'2013-3-12')declare @days intselect @days = case whe ...

  2. iOS UIView 快速修改 frame

    我们修改frame中的某个值,需要进行繁琐的书写,例如: (1). 直接设置位置大小 view.frame = CGRectMake(0, 0, 320, 150); (2). 只修改某个值 view ...

  3. 基于 HTML5 的数据存储

    以前想做个静态网页APP.最初的思路是用本地文件存储数据,后来发现在手机上运行时,文件无法找到. 经过了长达几个月的搜索(实际也就几天),没有找到合适的方法. 就在绝望的时候,无意间搜到基于HTML5 ...

  4. [GeekBand] C++11~14

    一.关键字decltype 由对象得到对象的数据类型,例如 Complex  a(1,  2);     decltype(a)  b(3,  4);     declare type是让编译器去找到 ...

  5. Junit的最简单样例:Hello world!

    我的技术博客经常被流氓网站恶意爬取转载.请移步原文:http://www.cnblogs.com/hamhog/p/3824934.html,享受整齐的排版.有效的链接.正确的代码缩进.更好的阅读体验 ...

  6. socket设置为非阻塞方式(windows和linux)

    Windows用以下方法将socket设置为非阻塞方式 : unsigned long ul=1; SOCKET s=socket(AF_INET,SOCK_STREAM,0); int ret=io ...

  7. WinForm条码打印

    在这篇博客中,我曾经介绍了如何实现条形码的生成(生成jpg格式的图片),这篇博客借用上面生成的条码,能够实现条形码的打印功能. 出于批量打印操作的方便以及操作体验考虑,我选择了WinForm.功能很简 ...

  8. DTCMS获取栏目子类

    <%set DataTable categoryList=get_category_child_list(channel,0)%> <%foreach(DataRow cdr in ...

  9. memcache的一致性hash算法

    <?php /** * 一致性哈希memcache分布式,采用的是虚拟节点的方式解决分布均匀性问题,查找节点采用二分法快速查找 * the last known user to change t ...

  10. php计算代码运行时间与内存使用的一段代码

    计算运行时间及内存使用,代码如下: <?php //开始计时 $HeaderTime = microtime(true);//参数true表示返回浮点数值 //代码 //... printf(& ...