Categroy方法覆蓋原理

在OC中可以通過Category給類添加屬性、方法、協(xié)議。

本文不介紹怎樣添加屬性、方法和協(xié)議,我們來分析一個相關問題:如果有多個Categroy中添加的方法和原類的方法重復定義,那么方法調(diào)用的行為是怎樣的呢?原理是怎樣的?

定義一個Person類以及兩個Person類的分類

@interface CLPerson : NSObject

- (void)work;

@end

@implementation CLPerson

- (void)work {
    NSLog(@"class = %@ | method = %s", [CLPerson class],__func__);
}

@end

@interface CLPerson (Method)

- (void)work;

@end

@implementation CLPerson (Method)

- (void)work {
    NSLog(@"class = %@ | method = %s", [CLPerson class],__func__);
}

@end

@interface CLPerson (Method2)

- (void)work;

@end

@implementation CLPerson (Method2)

- (void)work {
    NSLog(@"class = %@ | method = %s", [CLPerson class],__func__);
}

@end

調(diào)用Person類的work方法。

CLPerson *person = [[CLPerson alloc]init];
[person work];

輸出結果:
CategoryTest[44899:3185760] class = CLPerson | method = -[CLPerson(Method2) work]

從輸出結果我們可以看出,調(diào)用了Method2分類的work方法。

結論:方法調(diào)用會優(yōu)先選擇Category的方法。

那么為什么不是調(diào)用Method分類的work方法呢?

原因是:Category和原類的方法都會被添加到方法列表中,只是方法存在的順序不同。

文件排列順序

從圖中可以看出,Method2分類是排列在Method分類之后的,所以調(diào)用的是Method2的work方法。

結論:按照Category被添加到項目中的排列順序,后面被添加的Category會被優(yōu)先調(diào)用。

如果是系統(tǒng)的類是否會遵循這個規(guī)則?當然會遵循。

定義一個NSString的分類,實現(xiàn)一個NSString已有的方法。此處以stringByAppendingString:為示例。

@interface NSString (CLTest)

- (NSString *)stringByAppendingString:(NSString *)aString;

@end

@implementation NSString (CLTest)

- (NSString *)stringByAppendingString:(NSString *)aString {
    return self;
}

@end

NSString *str = @"Hello World!";
NSLog(@"after appending str = %@", [str stringByAppendingString:@"Hello World 2!"]);
    

輸出結果:
CategoryTest[45579:3224464] after appending str = Hello World!

從輸出結果我們可以看出,Hello World 2!并沒有被追加到原字符串后面。

結論:系統(tǒng)方法被Category中定義的方法覆蓋掉了。

下面我們來對這些結論做一個總結。

總結:

  1. 方法調(diào)用的時候優(yōu)先遍歷Category的方法。
  2. 如果有多個Category,后面被添加到項目里的Category會被優(yōu)先調(diào)用。
  3. 如果從方法列表中找到方法后,就不會繼續(xù)向后查找。

根據(jù)上文對Category方法覆蓋調(diào)用行為規(guī)則的總結,下面我們來對這些規(guī)則的原理做一個簡要的分析。

原理分析:

  1. 原類是在編譯期就直接編譯好的,而Category是在運行時動態(tài)地添加到原類中的。
  2. 那么,在類的方法列表中,原類的方法一定是早于Category的方法被添加。
  3. Category是按照文件加載順序被添加到原類中的。
  4. 方法調(diào)用的時候,后被添加的方法,會先被遍歷到,而一旦方法被找到,就會停止遍歷。

這就是原類方法會被Category方法覆蓋,并且優(yōu)先選擇排列在最后Category的原因了。

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

相關閱讀更多精彩內(nèi)容

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