Category为我们提供了区别于继承的另外一种方法来对类进行扩展。我们可以向任何已有的类添加成员函数来实现功能上的扩展(注:category只允许添加成员函数,不能添加数据成员),添加的函数可以访问类中所有的数据成员,该类的子类也将继承新添加的成员函数。
声明category
@interface 需要扩展的类(category名称)
//需要添加的函数
@end
实现category
@implementation 需要扩展的类(category名称)
//需要添加的函数
@end
category的局限性
1,无法向类中添加新的实例变量。2,名称冲突,即类别中的方法与现有方法重名,此时,类别方法具有更高的优先级。
category的作用
1,将类的实现分散到多个不同文件或多个不同框架中。这个是应对特别复杂的类。好多行代码放在一起看起来比较乱。
2,创建对私有方法的前向引用。
简单的说,就是创建一些个人认为的私有方法,只在category中声明。这样在@interface中不会出现其声明,在@implementation中的某些方法调用这些方法即可,这样便于组织和生成文档。
3,向对象添加非正式协议。
Cocoa中的类经常使用一种名为委托(delegate)的技术,委托是一种对象,另一个类的对象会要求委托对象执行它的某些操作。例如,当AppKit类的NSApplication启动时,它会询问其委托对象释放应该打开一个无标题窗口。
更常用的是,编写委托对象并将其提供给其他一些对象,通常是提供给Cocoa生成的对象。通过实现特定的方法,你可以控制Cocoa中的对象的行为。
所有这些委托对象与类别有什么关系呢?委托强调类别的另一种应用:被发送给委托对象的方法可以声明为一个NSObject的类别。
@interface NSObject(NSNetServiceBrowserDelegateMethods)
-(void) netServiceBrowserWillSearch:(NSNetServiceBrowser *) browser;
通过将这些方法声明为NSObject的类别,NSNetServiceBrowser的实现可以将这些消息之一发送给任何对象,无论这些对象实际上属于哪个类。这也意味着,只要对象实现了委托方法,任何类的对象都可以成为委托对象。
创建一个NSObject的类别成为“创建一个非正式协议”。非正式协议只是一种表达方式,它表示“这里有一些你可能希望实现的方法,因此你可以使用它们更好地完成工作”。
选择器
选择器只是一个方法名称,但它以Objective-C运行时使用的特殊方式编码,以快速执行查询。你可以使用@selector()预编译指令指定选择器,其中方法名称位于圆括号中。因此,Car类的setEngine:方法的选择器是:
@selector(setEngine:);
NSObject提供了一个名为respondsToSelector:的方法,该方法询问对象以确定其是否能够响应某个特定的消息。下面的代码段使用了respondsToSelector:方法:
ITunesFiner *finder = [[ITunesFinder alloc] init];
if([finder respondsToSelector:@selector(setEngines:)]){
NSLog(@"yowza!");
}
正式协议
正式协议就像Java的接口一样。事实上,Objective-C的协议正是受了Java接口的启发。和Java类似,单继承,但是可以实现多个接口。
声明协议:
@protocol NSCopying
- (id) copyWithZone: (NSZone *) zone;
@end
和@interface的声明是类似的。
采用协议
@interface Car: NSObject <NSCopying>
xxxx
@end//Car
同时实现两个协议就是
@interface Car: NSObject <NSCopying, NSCoding>
在新版本的objective-c中,增加了协议的一些可选项,@optional,@required,协议中的方法必须实现,不然会报错,但是如果以@optional修饰的话便没有这种限制,默认必须实现的方法其实就相当于以@required修饰。