利用OC的动态运行时分配机制,可以为现有的类添加新方法。这些新方法的OC术语称为“类别”category。
1、创建类别
类别是一种为现有的类添加新方法的方式。
1.1、声明类别
类别的声明格式与类的声明格式相似:
@interface NSString (NumberConvenience)
- (NSNumber *) lengthAsNumber;
@end
该声明具有两个特点:首先,现有的类位于@interface关键字之后,其后是位于圆括号中的一个新名称。(本例中的类别的名称是NumberConvenience,在NSString类中添加方法);其次,可以指定希望向其添加类别的类(在本例中是NSString)以及类别的名称(本例中是NumberConvenience)。之后列出添加的方法,最后以@end结束。
1.2、实现类别
与@interface部分对应的还有一个@implementation部分。
@implementation NSString (NumberConvenience)
- (NSNumber *) lengthAsNumber
{
...
}
@end
@implementation部分也包含类名、类别名以及新方法的正文部分。
类别创建后,该类别对应的类的对象可以调用类别的方法。
类别比创建子类方便些。
1.3、类别的局限性
类别有两方面的局限性:一是无法向类中添加新的实例变量,类别没有位置容纳实例变量。二是名称冲突,即类别中的方法与现有的方法重名。当发生名称冲突时,类别具有更高的优先级。
类别中的方法完全取代类中的初始方法,从无无法使用初始方法。
1.4、类别的作用
Cocoa中的类别主要用于3个目的:将类的实现分散到多个不同文件或多个不同框架中。创建对私有方法的前向引用,以及向对象添加非正式协议。
2、利用类别分散实现
一般将类的接口声明放入头文件中,将类的实现放入.m文件中。
不能将@implementation分散到多个不同的.m文件中。如果希望将大型的单个类分散到多个不同的.m文件中,可以使用类别来完成这一工作。
不但可以将一个类的实现分散到多个不同的源文件中,还可以将其分散到多个不同的框架中。
3、使用类别创建前向引用
Cocoa没有任何真正的私有方法。只要知道对象支持的某个方法的名称,即使该对象所在的类的接口中没有该方法的声明,也可以调用该方法。
4、非正式协议和委托类别
Cocoa中的类经常使用一种名为委托delegate的技术,委托是一种对象,另一个类的对象会要求委托对象执行它的某些操作。
4.2、委托和类别
委托强调类别的另一种应用:被发送给委托对象的方法可以声明为一个NSObject的类别。
通过将这些方法声明为NSObject的类别,被委托的类的实现可以将这些消息之一发送给任何对象,无论这些对象实际上属于哪个类。这也意味着,只要对象实现了委托方法,任何类的对象都可以成为委托对象。
通过这样创建NSObject的类别,任何类的对象都可以作为委托对象使用,既不需要从特定的委托类中继承,也不需要符合某个特定的接口。
创建一个NSObject的类别称为“创建一个非正式协议”。
4.3、响应选择器
选择器只是一个方法名称,但它以OC运行时使用的特殊方式编码,以快速执行查询。可以使用@selector() 预编译指令指定选择器,其中方法名位于圆括号中。
@selector(setEngine:)
4.4、选择器的其它应用
选择器可以被传递,可以作为方法的参数使用,甚至可以作为实例变量存储。这样可以生成一些非常强大和灵活的构造。