分類(category)和類擴展(extension)

分類(category在iOS開發(fā)中使用非常頻繁。尤其是在為系統(tǒng)類進行拓展的時候,我們可以不用繼承系統(tǒng)類,直接給系統(tǒng)類添加方法,最大程度的體現(xiàn)了Objective-C的動態(tài)語言特性。
分類運用場景舉例,想要收集每個頁面的啟動時間。
問題1:
項目中已經(jīng)有上百個頁面了,如果一個一個的加,浪費時間不說,以后增加了新頁面,還需要添加方法。
解決方法:
我們可以發(fā)現(xiàn)頁面都繼承了UIViewController,想要在每個頁面都執(zhí)行的代碼,可以寫在這些頁面的父類中。我們可以把代碼寫在UIViewController中。
問題2:
UIViewController是官方類,我們只能調(diào)用接口,并不能修改他的實現(xiàn)。
解決方法:
使用分類(category)。

1.分類(category)的作用
1).作用:可以在不修改原來類的基礎(chǔ)上,為一個類擴展方法。
2).最主要的用法:給系統(tǒng)自帶的類擴展方法。

2.分類中能寫點啥?
1).分類中只能添加“方法”,不能增加成員變量。
2).分類中可以訪問原來類中的成員變量,但是只能訪問@protect和@public形式的變量。如果想要訪問本類中的私有變量,分類和子類一樣,只能通過方法來訪問。
3).如果一定要在分類中添加成員變量,可以通過getter,setter手段進行添加,詳細:分類(category)添加屬性及成員變量

3.分類的書寫方法
假設(shè)我們有一個類,名叫Person,意義是人類。在person類中我們有一個方法,-(void)eat;意義是吃,因為每個人類都會吃。
人類有很多共同特點,也有很多不同點,比如,并不是每個人都會踢足球。這時候我寫一個分類,給喜歡運動的人,這個分類的名字叫做sport。因為是person類的分類,你會看到生成的名字叫做Person+sport。

分類的使用過程:聲明分類->實現(xiàn)分類->使用分類?
1).在項目中添加類,選擇Objective-C File,在?彈出的頁面中這樣配置。

創(chuàng)建.png

2).Person+sport.h頭文件

#import "Person.h"
@interface Person(sport)
- (void)palyFootBall;
@end

3).Person+sport.m文件

#import "Person+sport.h"
@implementation Person(sport)
- (void)palyFootBall {
    NSLog(@"分類在跑");
}
@end

4).回到最開始收集頁面啟動時間的問題,本類是系統(tǒng)的類,這里是UIViewController,我們可以使用分類擴展他的方法,也可以重寫他的方法,可以我需要在調(diào)用的地方加頭文件,所有子類都寫頭文件和直接在子類寫方法沒有什么區(qū)別,怎么樣可以使得不寫頭文件,子類就能調(diào)用我們寫的代碼呢?

回答:
我們可以進行方法交換(這樣可以不必在調(diào)用的地方增加頭文件),從而使得在實現(xiàn)的時候調(diào)用重寫的方法。具體實現(xiàn)以后會寫,TODO

4.分類的執(zhí)行優(yōu)先級
1).在本類和分類有相同的方法時,類別的方法優(yōu)先級較高,可覆蓋原類方法。
2).如果有兩個分類,他們都實現(xiàn)了相同的方法,如何判斷誰先執(zhí)行?分類執(zhí)行順序可以通過targets,Build Phases,Complie Source進行調(diào)節(jié),注意執(zhí)行順序是從上到下的。(只有兩個相同方法名的分類)

5.分類(category)和類擴展(extension)的關(guān)系
1).類擴展(extension)是category的一個特例,有時候也被稱為匿名分類。他的作用是為一個類添加一些私有的成員變量和方法。
2).類擴展能寫點啥?和分類不同,類擴展即可以聲明成員變量又可以聲明方法。
3).類擴展聽上去很復(fù)雜,但其實我們很早就認識它了。記得繼承自UIViewController的ViewController和繼承自NSObject的類有什么不同么?
4).繼承自UIViewController的ViewController類

#import "ViewController.h"
// 此處就是類擴展
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextField *myTextField;
- (IBAction)clickButtonA:(id)sender;
@end
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}
// 擴展方法的實現(xiàn)
- (IBAction)clickButtonA:(id)sender {
}
@end

5).對比看一下繼承自NSObject的類我們會發(fā)現(xiàn)沒有上面的代碼塊
@interface ViewController()//這就是類擴展的寫法
@end
6).類擴展可以定義在.m文件中,這種擴展方式中定義的變量都是私有的,也可以定義在.h文件中,這樣定義的代碼就是共有的,類擴展在.m文件中聲明私有方法是非常好的方式。
7).類擴展中添加的新方法,須在@implementation中實現(xiàn),否則編譯會報錯。category中沒有這種限制。
8).某些情況下,我們需要聲明一個@property,它對外是只讀的(readonly),而對內(nèi)是可讀寫的(readwrite),這時,可以通過Extensions實現(xiàn)
外部只能調(diào)用不可修改,內(nèi)部可以訪問修改的變量
注意事項
1.類別是類的擴展,只可以聲明方法,不可以聲明變量。并且,類別的方法優(yōu)先級較高,可覆蓋原類方法。
2.類別的方法中,不可以調(diào)用super方法。--類別的局限
3.category 方法可能會覆蓋于同一個類class 的其它 category 中的方法。但也可能被覆蓋,因為不法預(yù)知他們的加載優(yōu)先順序,出現(xiàn)這種情況通常會在編譯時出錯。如果在一個開發(fā)的SDK中使用了類別, 就最好保證類別名不同于使用者的類別名, 以及類別方法也不同于使用者的類別方法名, 通常通過加前綴來做到。

使用類別:
1.對框架提供類的擴展(沒有源碼,不能修改)。
2.不想生成一個新的子類的情況下,比如對 NSArray 的擴展。
3.方便做項目管理,可以將一份源碼在多個地方共享或者做方法版本管理、多人協(xié)作開發(fā)、用本地版本替換公共版本實現(xiàn)。

------整理

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

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

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