Objective-C 协议(protocol)
协议(protocol)是Objective-c中一个非常重要的语言特性,从概念上讲,非常类似于JAVA中接口. 一个协议其实就是一系列有关联的方法的集合(为方便后面叙述,我们把这个协议命名为myProtocol)。协议中的方法并不是由协议本身去实现,相反而是由遵循这个协议的其他类来实现。换句话说,协议myProtocol只是完成对协议函数的声明而并不管这些协议函数的具体实现。
声明一个协议的语法非常简单:
- @protocol myProtocol <NSObject>
- @required
- -(void) protocolNameA:(NSString*)string;
- @optional
- -(void) protocolNameB:(NSString*)string;
- @end
第一行是声明这个协议的名字为myProtocol。尖括号中的NSObject本身也是一个协议,其中定义了很多基本的协议函数,比如performSelector,isKindOfClass,respondsToSelector,conformsToProtocol,retain,release等。
协议接口分为required和optional两类。required顾名思义是说遵守这个协议的那个类“必须要”实现的接口,而optional则是可以实现也可以不实现的。协议接口的定义和普通的函数定义是一样的。
最后一行@end表示协议定义结束。这个协议的定义通常是在.h文件中。
定义一个类遵循这个协议:
- @interface myClass <myProtocol>
- @interface myClass :NSObject<myProtocol>
- @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:
- id <myProtocol> delegate;
这样,在编译阶段我们就可以知道用delegate所发送的消息是不是在它所遵循的myProtocol中的消息。好了, 到这里笔者钻起了牛角尖,我把id后面的 <myProtocol>删掉,然后用delegate发送一个并不存在于myProtocol中的消息,结果编译器还是给了“Instance method 'xxxx:' not found......”的警告信息。更奇怪的是,当发送一个存在于myProtocol中的消息时,编译器竟然没有这样的警告信息。这两个测试并不能说明之前的解释是错误的,姑且认为id<myProtocol> delegate这种写法是为了便于知道这个delegate遵循了myProtocol的协议吧。
Objective-C 协议(protocol)的更多相关文章
- iOS阶段学习第19天笔记(协议-Protocol)
iOS学习(OC语言)知识点整理 一.关于协议(Protocol)的介绍 1)概念:协议指多个对象之间协商的一个接口对象,协议提供了一些方法用在协议的实现者和代理者 之间通讯的一种方式 2) ...
- OC基础--分类(category) 和 协议(protocol)
OC 中的category分类文件相当于 C#中的部分类:OC 中的protocol协议文件(本质是头文件)相当于 C#中的接口.今天就简单说明一下OC中的这两个文件. 由于视频中的Xcode版本低, ...
- 协议Protocol
1.协议:是一组声明方法的集合,不能声明成员变量,作用类似于接口. 遵守此协议的类就相当于拥有了这个协议的所有方法的声明,如果父类遵守了某个协议,子类也遵守了这个协议. ...
- 浅谈iOS开发的协议(protocol)和代理(delegate)
协议和代理对于一个新手来说确实不讨好理解,也有很多的iOS开发的老手对此是懂非懂的.网上的很多博文只是讲了怎么使用,并没有说的很明白.下面我谈一下我的理解. 1.你要先搞明白,协议和代理为什么会出现, ...
- 关于ios object-c 类别-分类 category 的静态方法与私有变量,协议 protocol
关于ios object-c 类别-分类 category 的静态方法与私有变量,协议 protocol 2014-02-18 19:57 315人阅读 评论(0) 收藏 举报 1.category, ...
- Objective-C中的协议(Protocol)和类别(Category)
1.什么是协议? 2.协议与类别的声明和使用 1.什么是协议? 在Objective-C中,不支持多继承,即不允许一个类有多个父类,但是OC提供了类似的实现方法,也就是协议.协议有点类似于Java里的 ...
- Objective-C 中的协议(@protocol)和接口(@interface)的区别
Objective-C 中的协议(@protocol),依照我的理解,就是C#, Java, Pascal等语言中的接口(Interface).协议本身不实现任何方法,只是声明方法,使用协议的类必须实 ...
- Objective-C:继承、分类(Category、extension)、协议(protocol),个人理解,仅供参考
总结:继承.分类(Category.extension).协议(protocol) 一.继承: (1)特点: 继承多用于一般父类中的方法功能比较齐全,子类从父类继承过来使用,可以省略很多重复的代码 ...
- Objective-C:协议protocol
六.协议(protocol) 关键字:@optional.@required (1)是一个类共享的一个方法列表 (2)它声明了一系列的方法而不进行实现 (3)遵从某个协议,就是需要实现协议中的方法 ( ...
- 协议(Protocol)与委托代理(Delegate)
协议(Protocol)的作用: 1. 规范接口,用来定义一套公用的接口: 2. 约束或筛选对象. 代理(Delegate): 它本身是一种设计模式,委托一个对象<遵守协议>去做某件事情, ...
随机推荐
- sql server 判断日期当前月有多少天
declare @tm datetime set @tm = CONVERT(datetime,'2013-3-12')declare @days intselect @days = case whe ...
- iOS UIView 快速修改 frame
我们修改frame中的某个值,需要进行繁琐的书写,例如: (1). 直接设置位置大小 view.frame = CGRectMake(0, 0, 320, 150); (2). 只修改某个值 view ...
- 基于 HTML5 的数据存储
以前想做个静态网页APP.最初的思路是用本地文件存储数据,后来发现在手机上运行时,文件无法找到. 经过了长达几个月的搜索(实际也就几天),没有找到合适的方法. 就在绝望的时候,无意间搜到基于HTML5 ...
- [GeekBand] C++11~14
一.关键字decltype 由对象得到对象的数据类型,例如 Complex a(1, 2); decltype(a) b(3, 4); declare type是让编译器去找到 ...
- Junit的最简单样例:Hello world!
我的技术博客经常被流氓网站恶意爬取转载.请移步原文:http://www.cnblogs.com/hamhog/p/3824934.html,享受整齐的排版.有效的链接.正确的代码缩进.更好的阅读体验 ...
- socket设置为非阻塞方式(windows和linux)
Windows用以下方法将socket设置为非阻塞方式 : unsigned long ul=1; SOCKET s=socket(AF_INET,SOCK_STREAM,0); int ret=io ...
- WinForm条码打印
在这篇博客中,我曾经介绍了如何实现条形码的生成(生成jpg格式的图片),这篇博客借用上面生成的条码,能够实现条形码的打印功能. 出于批量打印操作的方便以及操作体验考虑,我选择了WinForm.功能很简 ...
- DTCMS获取栏目子类
<%set DataTable categoryList=get_category_child_list(channel,0)%> <%foreach(DataRow cdr in ...
- memcache的一致性hash算法
<?php /** * 一致性哈希memcache分布式,采用的是虚拟节点的方式解决分布均匀性问题,查找节点采用二分法快速查找 * the last known user to change t ...
- php计算代码运行时间与内存使用的一段代码
计算运行时间及内存使用,代码如下: <?php //开始计时 $HeaderTime = microtime(true);//参数true表示返回浮点数值 //代码 //... printf(& ...