协议
协议的声明
语法
@protocol 协议名
声明方法;
...
@end
方法的声明也可以使用属性声明。协议通常被作为头文件书写,并在类的声明之前导入。
协议的采用
当声明的类中实现了某个协议方法时,接口部分使用如下记述
语法:
@interface 类名 : 超类名 <协议名>
{
声明接口变量;
...
}
声明方法;
...
@end
使用这种声明时协议中的方法就被作为了类声明的一部分。一个类中可以同时采用多个协议,在接口部分的<>括号内,将多个协议名用逗号分隔即可。
@interface A : NSObject <S,T>
...
@end
另外,即使多个协议中重复包含同一个方法的声明也没有任何问题。假设S和T中都包含了方法copy:。只要在实现文件中实现了copy:方法,也就实现了协议S中的copy:方法和协议T中的copy:方法。==但是选择器相同而函数参数和返回值类型不一样,即签名不同的方法在协议中重复声明时就会产生问题。一个类内不能声明包含同一个选择器的另一个方法,也不能定义多个这样的协议。==
当协议中的方法在某个范畴中实现时就可以在该范畴中声明采用协议制定方法如下:
@interface 类名 (范畴名) <协议名>
声明方法;
...
@end
协议的继承
在某个协议中,可以追加另一组新的方法来产生新的协议,成为协议的继承。
@protocol 协议名1 <协议名2>
声明方法;
...
@end
这样声明的协议包含了继承的协议中的一组方法,以及新增的一组方法。协议还可以有多个继承源,增加多个继承源时在<>内将多个协议名用逗号分隔即可。
协议的前置声明
在定义文件中,为了让编译器能够检查类型,就必须用协议的定义
@protocol 协议名
协议适用性检查
在运行时可以动态地检查对象是否适用于某个协议,因此在程序中就有必要把协议当成数据来看待。使用编译器命令符@protocol()后,就可以获得表示指定协议数据的指针。
@protocol()
参数中包含类型(Protocol*)
可带入变量。
+(BOOL) conformToProtocol: (Protocol *) aProtocol;
//aProtocol参数指定的协议和类适用时,返回YES.
- (BOOL) conformToProtocol: (Protocol *) aProtocol;
接收器和参数aProtocol指定的协议适用时,返回YES.
若要检查对象obj是否适用于协议NSLocking采用如下方式:
if ([obj conformToProtocol]:@protocol(NSLocking))...
必选功能和可选功能
协议列举的方法中分为必须实现的方法和可选择实现的方法。在协议声明中,编译器命令@optional
和@required
可用来设定其后出现的方法是可选的还是必选的。@optional
和@required
命令符在声明中以什么样的顺序出现以及出现多少次都可以。若生命中没有特殊指定,那么默认为@required,表示方法是必选的。
@protocol Alarm
- (void)setCurrentTime:(NSDate *)date;
- @property (assign) BOOL alarm;
@optional
@property (assign) BOOL snooze;
- (void)pauseAlarm:(id)sender;
@required
- (void)setTimeAtHour: (int)h minute: (int)m;
@end