Objective-C——類別(Category)詳解

封裝是面向?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é)果如下:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容