封裝是面向?qū)ο蟮囊粋€(gè)特征,OC也不例外,但是有的時(shí)候我們會(huì)碰到這樣的情況,比如我封裝了一個(gè)類,不想再動(dòng)它了,可是隨著程序功能的增加,需要在那個(gè)類中增加一個(gè)小小的方法,這時(shí)我們就不必在那個(gè)類中做修改或者再定義一個(gè)子類,只需要在用到那個(gè)方法時(shí)隨手添加一個(gè)該類的類別(category)即可。
(1)在類別中定義的方法,會(huì)成為原始類中的一部分,與其他方法的調(diào)用沒有區(qū)別;
(2)通過給父類定義類別的方法,其子類也會(huì)繼承這些方法。如果子類添加類別方法,父類則不會(huì)擁有子類的類別方法;
類別方法的應(yīng)用:
(1)對(duì)現(xiàn)有類進(jìn)行擴(kuò)展:比如,你可以擴(kuò)展Cocoa Touch框架中的類,你在類目中增加的方法會(huì)被子類所繼承,而且在運(yùn)行時(shí)跟其他的方法沒有區(qū)別。
(2)作為子類的替代手段:不需要定義和使用一個(gè)子類,你可以通過類別直接向已有的類增加方法。
(3)對(duì)類中的方法歸類:利用category把一個(gè)龐大的類劃分為小塊來分別進(jìn)行開發(fā),從而更好的對(duì)類中的方法進(jìn)行更新和維護(hù)。
類別方法的局限性:
(1)無法向類別中添加新的實(shí)例變量,類別沒有位置來容納實(shí)例變量。如果想增加類的實(shí)例變量,只能通過定義子類的方式。
(2)如果在類別中覆蓋現(xiàn)有類的方法,會(huì)引起super消息的斷裂,因?yàn)轭悇e中的方法具有更高的優(yōu)先級(jí)。因此,一般不要覆蓋現(xiàn)有類中的方法。
類別的命名與用法:
類別的命名規(guī)則:類名+類別方法,如“NSString+Revert”
類別的接口聲明與類的定義十分類似,但類別不繼承父類,只需要帶有一個(gè)括號(hào),表明該類別的主要用途。
其實(shí)蘋果在設(shè)計(jì)OC的時(shí)候也是使用了類別的思想,最常見的就是在Foundation框架中。如NSArray所示:


下面我們通過代碼來實(shí)現(xiàn)一下Category類別。新建一個(gè)Command Line Tools程序。
【擴(kuò)展自定義的類】(1)新建一個(gè)Person類,在Person.h中實(shí)現(xiàn)如下:
#import<foundation foundation.h="">
@interfacePerson : NSObject
@property(nonatomic,strong) NSString *name;
- (void)test;
- (void)eat;
@end
//有可能我們?cè)谕粋€(gè)類中定義一個(gè)Category. 也可以新建一個(gè)Category文件;
@interfacePerson (Creation)
//實(shí)例方法
- (id)initWithName:(NSString*)aName;
@end
@interfacePerson (Life)
- (void)eat;
- (void)sleep;
- (void)play;
@end</foundation>
(2)在Person.m中實(shí)現(xiàn)如下:
#importPerson.h
@implementationPerson
- (void)test{
??NSLog(@這是原有類的一個(gè)方法);
}
//會(huì)被Category中的同名方法覆蓋;
- (void) eat{
??NSLog(@這是原有類的eat);
}
@end
@implementationPerson (Creation)
- (id)initWithName:(NSString *)aName{
??self = [superinit];
??if(self) {
????self.name = aName;
??}
??returnself;
}
@end
@implementationPerson (Life)
//當(dāng)你在原有類中實(shí)現(xiàn)一個(gè)相同方法的時(shí)候,這里會(huì)有一個(gè)警告。但是在調(diào)用的時(shí)候,Category中的同名方法會(huì)覆蓋原有類中的方法;
- (void)eat{
??NSLog(@他需要吃飯);
}
- (void)sleep{
??NSLog(@他需要睡覺);
}
- (void)play{
??NSLog(@他需要玩耍);
}
@end
(3)在main.m中實(shí)現(xiàn)如下:
#import<foundation foundation.h="">
#importPerson.h
intmain(intargc, constchar* argv[]) {
??@autoreleasepool{
? ? Person *jack = [[Person alloc] initWithName:@Jack];
????NSLog(@Person:%@,jack.name);
????[jack test];
????//調(diào)用Category中的方法;
????[jack eat];
????[jack sleep];
????[jack play];
??}
??return0;
}</foundation>
(4)打印結(jié)果如下:

【擴(kuò)展系統(tǒng)提供的類】
(1)我們以NSArray類為例,增加NSArray中的方法。新建一個(gè)Convert類別來自于NSArray,方法用來使數(shù)組中元素逆轉(zhuǎn)。在NSArray+Convert.h中實(shí)現(xiàn)如下:
#import<foundation foundation.h="">
@interfaceNSArray (Convert)
//為NSArray增加一個(gè)方法;
+ (NSMutableArray*)arrayFromNumber:(int)number;
@end</foundation>
(2)在NSArray+Convert.m中實(shí)現(xiàn)如下:
#importNSArray+Convert.h
@implementationNSArray (Convert)
+ (NSMutableArray*)arrayFromNumber:(int)number{
??NSMutableArray *numberArray = [[NSMutableArray alloc] init];
??while(number) {
????intlast = number % 10;//取出最后一位;
????number /= 10;?? //去掉一位;
????[numberArray addObject:[NSNumber numberWithInt:last]];
??}
??returnnumberArray;
}
@end
(3)在main.m中實(shí)現(xiàn)如下:
#import<foundation foundation.h="">
#importNSArray+Convert.h
int main(int argc, constchar* argv []) {
??@autoreleasepool{
????NSMutableArray *numberArray = [NSArray arrayFromNumber:123];
????for(NSNumber *number in numberArray) {
??????NSLog(@number:%@,number);
????}
? }
??return0;
}</foundation>
(4)打印結(jié)果如下:
