Objective-C中的类别(Category)主要有两大功能,一个是将类的相关方法进行分组,另一个是无需继承即可向现有的类添加新的方法以扩展其功能。
例如,您所在的开发团队需要创建一个类,每个团队成员负责类的某一部分功能,例如成员A负责编写对象的创建与释放的方法、成员B负责编写网络通信的方法、成员C负责数据的家在与保存方法等。iOS SDK中大量使用了类别,这里以NSArray类的外部接口声明为例(代码中以...省略了其他方法的接口声明):
@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration>
- (NSUInteger)count;
- (id)objectAtIndex:(NSUInteger)index;
@end
@interface NSArray (NSExtendedArray)
- (NSArray *)arrayByAddingObject:(id)anObject;
- (NSArray *)arrayByAddingObjectsFromArray:(NSArray *)otherArray;
- (NSString *)componentsJoinedByString:(NSString *)separator;
...
@end
@interface NSArray (NSArrayCreation)
+ (id)array;
+ (id)arrayWithObject:(id)anObject;
...
@end
@interface NSArray (NSDeprecated)
- (void)getObjects:(id __unsafe_unretained [])objects;
@end
注意类别的名字在小括号中,并且位于源类名之后。例如NSExtendedArray是类别名称,它扩展了NSArray类。
类别方法的实现格式如下:
@implementation NSArray (NSArrayCreation)
+ (id)array
{
...
}
...
@end
类别的实现部分可以放在类的实现文件中,也可以放在额外的实现文件中。
以上介绍的是有名的类别,有名的类别中只能添加静态方法或者实例方法,不能添加成员变量、属性。类别还有一种特殊的使用方式是创建无名的类别(也叫类的扩展),即括号内为空,例如(TestObject是一个类):@interface TestObject ()
@property int extensionValue;
-(void)setExtensionName:(NSString*)name;
@end
注意到无名类别除了可以添加方法之外,还允许向类添加额外的成员变量和属性,它们的实现需要放在类的实现部分中。例如:
@implementation TestObject
@synthesize value = _value; //实现在类的外部接口中声明的value属性
@synthesize extensionValue = _extensionValue; //实现在无名类别中声明的extensionValue属性
-(void)setExtensionName:(NSString*)name
{
NSLog(@"%d, %@", _extensionValue, name);
}
...
//实现其他类的方法
...
@end
注意无名类别中添加的方法,其访问级别为私有(@private),你可以在其中添加类的内部私有方法和成员。
#import "TestClass.h"
int main(int argc, const char * argv[])
{
@autoreleasepool
{
TestClass* tc1 = [[[TestClass alloc] init] autorelease];
tc1.extensionValue = 2; //编译错误,私有成员无法访问
}
return 0;
}
以上代码无法通过编译,原因是在类扩展中定义的成员均为私有。
另外需要注意的是,类别的数量不受限制,一个类可以有很多的类别。类别中定义的方法的优先级高于类中定义的方法,也就是说当你在类别中定义了一个与源类中的签名完全一致的方法时,类别中的方法会完全覆盖源类中的方法,你无法调用源类中的方法。