封裝是面向對象的一個特征,OC也不例外,但是有的時候我們會碰到這樣的情況,比如我封裝了一個類,不想再動它了,可是隨著程序功能的增加,需要在那個類中增加一個小小的方法,這時我們就不必在那個類中做修改或者再定義一個子類,只需要在用到那個方法時隨手添加一個該類的類別(category)即可。
(1)在類別中定義的方法,會成為原始類中的一部分,與其他方法的調用沒有區別;
(2)通過給父類定義類別的方法,其子類也會繼承這些方法。如果子類添加類別方法,父類則不會擁有子類的類別方法;
類別方法的應用:
(1)對現有類進行擴展:比如,你可以擴展Cocoa Touch框架中的類,你在類目中增加的方法會被子類所繼承,而且在運行時跟其他的方法沒有區別。
(2)作為子類的替代手段:不需要定義和使用一個子類,你可以通過類別直接向已有的類增加方法。
(3)對類中的方法歸類:利用category把一個龐大的類劃分為小塊來分別進行開發,從而更好的對類中的方法進行更新和維護。
類別方法的局限性:
(1)無法向類別中添加新的實例變量,類別沒有位置來容納實例變量。如果想增加類的實例變量,只能通過定義子類的方式。
(2)如果在類別中覆蓋現有類的方法,會引起super消息的斷裂,因為類別中的方法具有更高的優先級。因此,一般不要覆蓋現有類中的方法。
類別的命名與用法:
類別的命名規則:類名+類別方法,如“NSString+Revert”
類別的接口聲明與類的定義十分類似,但類別不繼承父類,只需要帶有一個括號,表明該類別的主要用途。
其實蘋果在設計OC的時候也是使用了類別的思想,最常見的就是在Foundation框架中。如NSArray所示:
。
。
下面我們通過代碼來實現一下Category類別。新建一個Command Line Tools程序。
【擴展自定義的類】(1)新建一個Person類,在Person.h中實現如下:
#import@interface Person : NSObject @property(nonatomic,strong) NSString *name; - (void)test; - (void)eat; @end //有可能我們在同一個類中定義一個Category. 也可以新建一個Category文件; @interface Person (Creation) //實例方法 - (id)initWithName:(NSString*)aName; @end @interface Person (Life) - (void)eat; - (void)sleep; - (void)play; @end
#import Person.h @implementation Person - (void)test{ NSLog(@這是原有類的一個方法); } //會被Category中的同名方法覆蓋; - (void) eat{ NSLog(@這是原有類的eat); } @end @implementation Person (Creation) - (id)initWithName:(NSString *)aName{ self = [super init]; if (self) { self.name = aName; } return self; } @end @implementation Person (Life) //當你在原有類中實現一個相同方法的時候,這裡會有一個警告。但是在調用的時候,Category中的同名方法會覆蓋原有類中的方法; - (void)eat{ NSLog(@他需要吃飯); } - (void)sleep{ NSLog(@他需要睡覺); } - (void)play{ NSLog(@他需要玩耍); } @end
#import#import Person.h int main(int argc, const char * argv[]) { @autoreleasepool { Person *jack = [[Person alloc] initWithName:@Jack]; NSLog(@Person:%@,jack.name); [jack test]; //調用Category中的方法; [jack eat]; [jack sleep]; [jack play]; } return 0; }
。
【擴展系統提供的類】
(1)我們以NSArray類為例,增加NSArray中的方法。新建一個Convert類別來自於NSArray,方法用來使數組中元素逆轉。在NSArray+Convert.h中實現如下:
#import@interface NSArray (Convert) //為NSArray增加一個方法; + (NSMutableArray*)arrayFromNumber:(int)number; @end
#import NSArray+Convert.h @implementation NSArray (Convert) + (NSMutableArray*)arrayFromNumber:(int)number{ NSMutableArray *numberArray = [[NSMutableArray alloc] init]; while (number) { int last = number % 10;//取出最後一位; number /= 10; //去掉一位; [numberArray addObject:[NSNumber numberWithInt:last]]; } return numberArray; } @end
#import#import NSArray+Convert.h int main(int argc, const char * argv[]) { @autoreleasepool { NSMutableArray *numberArray = [NSArray arrayFromNumber:123]; for (NSNumber *number in numberArray) { NSLog(@number:%@,number); } } return 0; }
。