您的位置:首页 > 移动开发 > Objective-C

OC基础回顾(十二)协议

2015-08-20 14:04 429 查看
在OC基础(十一)中我们讨论了类别和非正式协议的奇妙之处。在使用非正式协议时,可以只实现你想要获得响应的方法。也不必在对象中声明任何内容来表示该对象可用作委托对象。所有这些任务可以用最少的代码完成。
下面来学习正式协议。

1. 正式协议

     与非正式协议一样,正式协议包含了方法和属性的有名称列表。但与非正式协议不同的是,正式协议需要显示地采用。采用(adopt)协议的办法是在类的@interface声明中列出协议的名称。采用协议后,你的类就要遵守该协议。采用协议就意味着你承诺实现该协议的所有方法。否则,编译器会生成警告来提醒你。

1.1 声明协议

声明一个协议的方法非常简单:
@protocol myProtocol <NSObject>
@required
-(void)protocolMethodA:(NSString *)string;
@optional
-(void)protocolMethodB:(NSString *)string;
@end


说明:
(1)第一行是声明这个协议的名字为myProtocol。尖括号中的NSObject本身也是一个协议,其中定义了很多基本的协议函数,比如performSelector,isKindOfClass,respondsToSelector,conformsToProtocol,retain,release等。
(2)协议接口分为required和optional两类。required顾名思义是说遵守这个协议的那个类“必须要”实现的接口,而optional则是可以实现也可以不实现的。协议接口的定义和普通的函数定义是一样的。
(3)最后一行@end表示协议定义结束。这个协议的定义通常是在.h文件中。

1.2 定义一个类遵循这个协议

@interface myClass <myProtocol>
@intrerface myClass : NSObject <myProtocol>
@interface myClass : NSObject <myProtocol, NSCoding>

说明:
上面分别是三种不同的情况。编译的时候编译器会自动检查myClass是否实现了myProtocol中的必要的(@required)接口。如果没有实现则会发出一个警告信息。另外需要注意的是,如果有继承自myClass的子类,这些子类也是会自动遵循myClass所遵循的协议的,而且也可以重载这些接口。

2.为什么要使用正式协议

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

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的控制。

3.关于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 协议