1.正式协议
与非正式协议一样,正式协议是包含了方法和属性的有名称列表。但与非正式协议不同的是,正式协议要求显式的采用。采用(adopt)协议的办法是在类的@interface声明中列出协议名称。采用协议后,你的类就要遵守该协议。采用协议就意味着你承诺实现该协议的所有方法。否则,编译器会生成警告来提醒你。
1.1声明协议
如下,如果采用了NSCopying协议,对象将会知道如何创建自身的副本。
@protocol NSCopying
- (id) copyWithZone:(NSzone *) zone;
@end
声明协议的语法看起来和声明类或类别的语法有点像,不过这里使用的不是@interface,而是使用@protocol告诉编译器:“下面将是一个新的正式协议”。@protocol后面是协议名称,协议名称必须要唯一。
也可以继承父协议,这点与继承父类相似。在声明语句协议名称后面的尖括号内可以指定父协议的名称。
@protocol MySuperDuberProtocol <MyParentProtocol>
@end
第一行代买表示MySuperDuperProtocol协议继承于MyParentProtocol协议,因此必须实现两个协议中所有需要实现的方法。通常可以使用NSObject作为根协议。不要将其与NSObject类混淆。NSObject类复合NSObject协议,这意味着所有的对象都符合NSObject协议。将NSObject协议作为编写的协议是一个不错的方式。
1.2采用协议
要采用某个协议,可以在类的生声明中列出该协议的名称,并用尖括号括起来。例如,Car类想要采用NSCopying协议,则其类的声明会如下所示。
@interface Car : NSObject <NSCopying>
{
//instance variables
}//methods
@end //Car
而如果Car类要同时采用NSCopying和NSCoding两个协议,则其类声明将如下所示。
@interface Car: NSObject<NSCopying,NSCoding>
{
}
@end
1.3协议和数据
id类型表示一个可以指向任何类型的对象的指针,它是一个泛型对象类型。可以将任何对象复制给一个id类型的变量,也可以将一个id类型的变量复制给任何对象的对象指针。如果一个用尖括号括起来的协议名称跟随在id之后,则编译器将知道我们会接受任意类型的对象,但前提是遵守该协议。
例如,NSControl类中有一个名为setObjectValue:地方法,该方法要求对象遵守NSCopyin协议。
- (void) setObjectValue: (id<NSCopying>) object;
编译器在编译该方法时,将检查参数类型,如果没有遵守协议则提出警告。