转载:http://book.51cto.com/art/201105/262265.htm
category是Objective-C里面最常用到的功能之一。category可以为已经存在的类增加方法,而不需要增加一个子类。另外,category使得我们在不知道某个类的内部实现的情况下,为该类增加方法。
如果我们想增加某个框架(framework)中的类的方法,category就非常有效。比如,如果想在NSString上增加一个方法来判断它是否是一个URL,那就可以这么做:
#import ……
@interface NSString (Utilities)
- (BOOL) isURL;
@end
这跟类的定义非常类似,区别就是category没有父类,而且在括号里面要有category的名字。名字可以随便取,但是名字应该让人比较明白category里面有些什么功能的方法。下面的例子添加了一个判断URL的方法。
#import "NSStringUtilities.h"
@implementation NSString (Utilities)
- (BOOL) isURL
{
if ( [self hasPrefix:@"http://"] )
return YES;
else
return NO;
}
@end
现在可以在任何的NSString类对象上调用这个方法了。下面的代码在控制台上打印“string1 is a URL”。
NSString*string1= @"http://www.xinlaoshi.com/";
NSString*string2= @"Pixar";
if ( [string1 isURL] )
NSLog (@"string1 is a URL");
if ( [string2 isURL] )
NSLog (@"string2 is a URL");
从上面的例子看出,通过类别所添加的新方法就成为类的一部分。我们通过类别为NSString添加的方法也存在于它的方法列表中,而为NSString子类添加的新方法,NSString类是不具有的。通过类别所添加的新方法可以像这个类的其他方法一样完成任何操作。在运行时,新添加的方法和已经存在的方法在使用上没有任何区别。通过类别为类所添加的方法和别的方法一样会被它的子类所继承。
类别接口的定义看起来很像类接口定义,而不同的是类别名使用圆括号列出,它们位于类名后面。类别必须导入它所扩展的类的接口文件。标准的语法格式如下:
#import "类名.h"
@interface类名(类别名)
//新方法的声明
@end
和类一样,类别的实现也要导入它的接口文件。一个常用的命名约定是,类别的基本文件名是这个类别扩展的类的名字后面跟类别名。因此,一个名字为“类名”+“类别名”+“.m”的实现文件看起来就像这样:
#import "类名类别名.h"
@implementation类名(类别名)
//新方法的实现
@end
注意,类别并不能为类声明新的实例变量,它只包含方法。然而,在类作用域中的所有实例变量,都能被这些类别方法所访问。它们包括为类声明的所有实例变量,甚至那些被@private修饰的变量。可以为一个类添加多个类别,但每个类别名必须不同,而且每个类别都必须声明并实现一套不同的方法。
要记住的是,当我们通过category来修改一个类的时候,它对应用程序里的这个类的所有对象都起作用。跟子类不一样,category不能增加成员变量。我们还可以用category来重写类原先的存在的方法(我们并不推荐读者这么做)。最后下面给出本节的完整例子。
【例5-4】categories实例。
NSStringUtilities.h的代码如下:
#import/Cocoa.h>
@interface NSString (Utilities)
-(BOOL)isURL;
@end
NSStringUtilities.m的代码如下:
#import "NSStringUtilities.h"
@implementation NSString (Utilities)
-(BOOL)isURL{
if ([self hasPrefix:@"http://"]) {
return YES;
}else {
return NO;
}
}
@end
测试类UseCategories.m的代码如下:
#import/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool *pool= [[NSAutoreleasePool alloc] init];
NSString *string1= @"http://www.xinlaoshi.com/";
NSString *string2= @"Pixar";
if ([string1 isURL]) {
NSLog(@"string1 is a URL");
}else {
NSLog(@"string1 is not a URL");
}
if ([string2 isURL]) {
NSLog(@"string2 is a URL");
} else {
NSLog(@"string2 is not a URL");
}
[pool drain];
return 0;
}
【程序结果】
string1 is a URL
string2 is not a URL
网友评论