9 分类和协议 [Objective-C基础教程]

通过分类 (category) 可以以模块的方式向现有的类添加方法。它提供了一种简单的方式,用它可以将 类
的定义模块化到相关方法的组或分类中。它还提供了扩展现有类定义的简便方式,并且不必访问类的源 代
码,也无需创建子类。
对于 Fraction 类,除了将两个分数相加的 add: 方法外,还想要拥有将两个分数相减、相乘和相除的方
法。
//**********************************************************************************************//
// Fraction 类声明
#import<Foundation/Foundation.h>
@interface Fraction : NSObject
{
int numerator;
int denominator;
}
@property int numerator, deniminator;
-(void) setTo: (int) n over: (int) d;
-(Fraction *) add: (Fraction *) f; // 声明分数的 加法函数
-(void) print;

@end
//*********************************************************************************************//
现在,从接口部分删除 add: 方法,并将其添加到新 分类 ,同时添加其他三种要实现的数学运算。看 一
下新 MathOps 分类的接口部分。
//*********************************************************************************************//
#import<Foundation/Foundation.h>
#import "Fraction.h"
@interface Fraction (MathOps)
-(Fraction *) add: (Fraction *) f; // 加法函数

-(Fraction *) mul: (Fraction *) f; // 乘法函数
-(Fraction *) sub: (Fraction *) f; // 减法函数
-(Fraction *) div: (Fraction *) f; // 除法函数
@end
//*********************************************************************************************//
// #inport "Fraction.h" 这里既是分类接口部分的定义,也是对现有接口部分的扩展,所以必须包括原始接口部分
// @interface Fraction (MathOps) 告诉编译器正在为 Fraction Fraction Fraction Fraction 类定义新的分类,名称为 MathOps MathOps MathOps MathOps 。
可以在一个实现文件中定义 Fraction.h 接口部分中的所有方法,以及 MathOps 分类中的所有方法。
也可以在单独的实现部分定义分类的方法。在这种情况下,这些方法的实现部分还必须找出方法所 属
的分类。与接口部分一样,通过将分类名称括在类名称之后的圆括号中来确定方法所属的分类,如下所 示 :
@implementation Fraction (MathOps)
// code for category methods

@end

关于分类的一些注意事项
A 、 尽管分类可以访问原始类的实例变量,但是它不能添加自身的任何变量。如果需要添加变 量 ,
可以考虑创建子类。
B 、 分类可以重载该类中的另一个方法,但是通常认为这种做法不可取。因为,重载之后,再 不
能访问原来的方法。
C 、 可以拥有很多分类。
D 、 和一般接口部分不同的是,不必实现分类中的所有方法。这对于程序扩展很有用,可以在 该
分类中声明所有方法,然后在一段时间之后才实现它。
E 、 通过使用分类添加新方法来扩展类不仅会影响这个类,同时也会影响它的所有子类。

9.2 协议
协议的声明类似于类接口的声明,有一点不同的是,协议没有父类,并且不能定义成员变量。下面 的
例子演示了只有一个方法的协议的声明:
@protocol MyProtocol

- (void)myProtocolMethod;
@end
协议是多个类共享的一个方法列表,协议中列出的方法没有相应的实现。如果一个类采用 MyProtoco l
协议,则必须实现名为 myProtocolMethod 的方法。
通过在 @interface 行的一对尖括号 <...> 内列出协议名称,可以告知编译器你正在采用一个协议。这项
协议的名称放在类名和它的父类名称之后,如下所示:
@interface AddressBook : NSObject < myProtocol >
这说明, AddressBook 是父类为 AddressBook 的对象,并且它遵守 myProtocolMethod 协议。在
AddressBook 的实现部分,编译器期望找到定义的 myProtocolMethod 方法。
如果采用多项协议,只需把它们都列在尖括号中,用逗号分开:
@interface AddressBook : NSObject < myProtocol , your Protocol >
以上代码告知编译器 AddressBook 类采用 myProtocolMethod 和 your ProtocolMethod 协议。这次,编
译器将期望在 AddressBook 的实现部分看到为这些协议列出的所有方法的实现。

有关协议的注意事项:
A 、如果一个类遵守某项协议,那么它的子类也遵守该协议。
B 、协议不引用任何类,它是无类的( classless )。任何类都可以遵守某项协议。
C 、通过在类型名称之后的尖括号中添加协议名称,可以借助编译器的帮助来检查变量的一致性,如
下:
id <Drawing> currentObject;
这告知编译器 currentObject 将包含遵守 Drawing 协议的对象。如果向 currentObject 指派静态类型的 对
象,这个对象不遵守 Drawing 协议,编译器将给出 warning 。
再次提到 id 类型,如果向 currentObject 指派一个 id 变量,不会产生这条消息,因为编译器不知道存
储在 id 变量中的对象是否遵守 Drawing 协议。
D 、如果这个变量保存的对象遵守多项协议,则可以列出多项协议,如下:
id <Drawing, Drawing 1> currentObject;
E 、定义一项协议时,可以扩展现有协议的定义。以下协议
@protocol Drawing3D <Drawing>
说明 Drawing3D 协议也采用了 Drawing 协议。因此采用 Drawing3D 协议的类都必须实现此协议列出
的方法,以及 Drawing 协议的方法。

F 、分类也可以采用一项协议,如:

@interface Fraction (stuff) <NSCopying, NSCoding>
此处, Fraction 拥有一个分类 stuff ,这个分类采用了 NSCopying 和 NSCoding 协议。

来源://作者:/更新时间:2012-11-09
相关文章
评论:
验证码:
匿名评论:

最新文章

新热推荐

文章排行