Category是ObjC語言中的擴充機制之一,另一個為Protocol。
Category提供一種為某個類添加方法而又不必編寫子類的途徑。
假設有這樣一個類CarInfo:
#import <Foundation/Foundation.h>
@interface CarInfo : NSObject {
}
-(void)sayCarBrand;
@end
@implementation CarInfo
-(void) sayCarBrand{
NSLog(@"Car brand: Golf");
}
@end
我可以用Category為該類增加新的方法:
#import <Foundation/Foundation.h>
#import "CarInfo.h"
@interface CarInfo(CarInfoCategory)
-(void)sayCarBrandChinese;
@end
@implementation CarInfo(CarInfoCategory)
-(void)sayCarBrandChinese{
NSLog(@"汽車品牌:高爾夫");
}
@end
這裡的Category增加了一個新的方法,用來顯示漢字名稱。可在其他代碼中直接調用,就如同調用CarInfo其他執行個體方法一樣:
CarInfo *carInfo=[[CarInfo alloc] init];
[carInfo sayCarBrandChinese];
這種效果是Java做不到的。這得益于ObjC語言方法排程程式這一特殊機制。
如果方法名稱相同會怎樣?比如:
#import <Foundation/Foundation.h>
#import "CarInfo.h"
@interface CarInfo(CarInfoCategory)
-(void)sayCarBrand;
@end
@implementation CarInfo(CarInfoCategory)
-(void)sayCarBrand{
NSLog(@"汽車品牌:高爾夫");
}
@end
再次調用:
CarInfo *carInfo=[[CarInfo alloc] init];
[carInfo sayCarBrand];
會發現,列印的是category中的方法,而不是類的執行個體方法。因為category優先于類執行個體方法。
那麼是否有這樣的能力,比如在category的方法内代碼中調用類的執行個體方法,這樣不就可以實作類似Java方法攔截器的功能了麼?或者說是方法代理模式。遺憾的是,這樣不可以。
原文連結:http://marshal.easymorse.com/archives/4183
Objective C 2.0 簡明教程 Category
Category為我們提供了差別于繼承的另外一種方法來對類進行擴充。我們可以向任何已有的類添加成員函數來實作功能上的擴充(注:category隻允許添加成員函數,不能添加資料成員),添加的函數可以通路類中所有的資料成員,該類的子類也将繼承新添加的成員函數。
假設我們需要擴充前面幾節用到的book類,添加一個名為Abstract的成員函數來輸出書籍的摘要。使用category的格式為:
在頭檔案中聲明category:
@interface 需要擴充的類(category名稱)
//需要添加的函數
@end
可以看到,聲明category的方法同類的聲明非常類似。回到我們的例子,如果我們需要向Book類添加Abstract成員函數,對應的聲明檔案如下所示
// Book+Abstract.h
#import <Cocoa/Cocoa.h>
#import "Book.h"
@interface Book(Abstract)
-(NSString*) Abstract;
@end
注意推薦的檔案命名規則:類名+category名.h
接下來我們需要對添加的abstract函數進行定義,如下所示:
// Book+Abstract.m
#import "Book+Abstract.h"
@implementation Book(Abstract)
-(NSString*)Abstract{
NSString* retstr = [[NSString alloc]initWithString:@"The story is..."];
[retstr autorelease];
return retstr;
}
@end
implementation檔案的命名規則與頭檔案相似:類名+category名.m
作為示範,我們隻是在Abstract函數中簡單的輸出一個NSString。下面我們來看用戶端如何調用:
#import <Foundation/Foundation.h>
#import "Book.h"
#import "Book+Abstract.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString* name = [[NSString alloc] initWithString:@"Harry Porter"];
NSNumber* number = [[NSNumber alloc] initWithInt:100];
Book *book = [[Book alloc] initWithTitle:name andNumofpages:number];
[number release];
[name release];
NSLog(@"Abstract: %@", [book Abstract]);
[book release];
[pool drain];
return 0;
}