Category
無論一個類設(shè)計的如何完美,都不可避免的會遇到?jīng)]有預(yù)測到的需求,那怎么擴(kuò)展現(xiàn)有的類呢?當(dāng)然,繼承是個不錯的選擇。但是Objective-C提供了一種特別的方式來擴(kuò)展類,叫Catagory,可以動態(tài)的為已經(jīng)存在的類添加新的行為。這樣可以保證類的原原來的基礎(chǔ)上,較小的改動就可以增加需要的功能。使用Category對類進(jìn)行擴(kuò)展時,不需要訪問其源代碼,也不需要創(chuàng)建子類,這樣我們可以擴(kuò)展系統(tǒng)提供的類。Category使用簡單的方式,實現(xiàn)了類的相關(guān)方法的模塊化,把不同的類方法分配到不同的分類文件中。
通過一個簡單的例子看看Category如何使用。
現(xiàn)在我們有一個類叫MyClass
?
好了,有了上面的MyClass后,我們要在不增加子類,不修改MyClass類的情況下增加一個HelloWorld的方法,怎么添加呢?只需添加兩個文件MyClass+HelloWorld.h ?和?MyClass+HelloWorld.m。
在聲明文件和實現(xiàn)文件中用“()”把Category的名稱括起來。原類名+Category”的這是約定的文件命名方式。
Category on的類是MyClass,選對了哦
這樣Xcode就幫你創(chuàng)建了MyClass+HelloWorld.h ?和?MyClass+HelloWorld.m這兩個文件了。
那么我們現(xiàn)在添加一個HelloWorld方法。看看實現(xiàn)后的代碼如下:
?
?
?
?
運行打印結(jié)果:
?
?
那的Category的使用場景有那些呢:
1、類包含了很多個方法實現(xiàn),而這些方法需要不同團(tuán)隊的成員來實現(xiàn)
2、當(dāng)你在使用基礎(chǔ)類庫中的類時,你不想繼承這些類而只想添加一些方法時。
?
Category能實現(xiàn)上面的需求,當(dāng)然也有使用Category是需要注意的問題:
1、Category可以訪問原始類的實例變量,但不能添加實例變量,如果想添加變量,那就通過繼承創(chuàng)建子類來實現(xiàn)。
2、Category可以重載原始類的方法,不大不推薦這么做,這樣會覆蓋掉原始類的方法。如果確實要重載,那就通過繼承創(chuàng)建子類來實現(xiàn)。
3、和普通接口有所區(qū)別的是,在Category的實現(xiàn)文件中的實例方法只要你不去調(diào)用它你可以不用實現(xiàn)所有聲明的所有方法。
1. 擴(kuò)展類的功能
Category提供了一種比繼承(inheritance)更為簡潔的方法來對class進(jìn)行擴(kuò)展,我們可以為任何已經(jīng)存在的class添加方法(不包括數(shù)據(jù)成員)卻不需要訪問該class的實現(xiàn)文件。
新添加的方法和原有的方法具有同等的地位,可以訪問class的數(shù)據(jù)成員,并且完全植入到class的繼承體系之中,子類同樣會繼承新添加的方法。 利用category對類進(jìn)行擴(kuò)展可以避免使類的繼承體系過于臃腫,復(fù)雜,降低了維護(hù)成本。另外,新添加的方法如果和已經(jīng)存在的方法具有相同的 prototype,那么新添加的方法將會覆蓋已經(jīng)存在的方法,也就是category使得使得在沒有源文件時修改已存在class的 functionality或者清除bug成為可能,所有該class的對象的行為都將發(fā)生變化,這一點是繼承無法達(dá)到的。
可以在以下情況使用Category
- 當(dāng)你在定義類的時候,在某些情況下(例如需求變更),你可能想要為其中的某個或幾個類中添加方法。
- 一個類中包含了許多不同的方法需要實現(xiàn),而這些方法需要不同團(tuán)隊的成員實現(xiàn) (有點意思,不知實踐中效果如何)
- 當(dāng)你在使用基礎(chǔ)類庫中的類時,你可能希望這些類實現(xiàn)一些你需要的方法。
?
使用方法:“原類名+Category”的方式命名,例子如下:
(1)定義與實現(xiàn)
NSString+Background.h?(給NaviationBar新添加的一個Category)
#import <UIKit/UIKit.h>@interface UINavigationBar (Background) - (void)setNavgationBarBg; @end?
NSString+Background.m
#import "UINavigationBar+Background.h"@implementation UINavigationBar (Background)- (void)setNavgationBarBg {UIImage * TitleBarImage = [UIImage imageNamed:@"Navigationbar_bg.png"];if([self respondsToSelector:@selector(setBackgroundImage:forBarMetrics:)]){[self setBackgroundImage:TitleBarImage forBarMetrics:UIBarMetricsDefault];} } @end?
(2)調(diào)用
#import?NSString+Background.h
2. 模擬私有方法/函數(shù)
在.m中,實現(xiàn)私有方法。
Foo.m
#impot Foo.h@interface Foo (private) - (void) testPrivate; @end@implementation Foo- (void) test {[self testPrivate]; }- (void) testPrivate {NSLog(@"testPrivate Executed"); }@end?
3.缺點
- Category可以訪問原始類的實例變量,但不能添加變量,如果想添加變量,可以考慮通過繼承創(chuàng)建子類。
- Category可以重載原始類的方法,但不推薦這么做,這么做的后果是你再也不能訪問原來的方法。如果確實要重載,正確的選擇是創(chuàng)建子類
- 名稱沖突,即當(dāng)類別中的方法與原始類方法名稱沖突時,類別具有更高的優(yōu)先級。類別方法將完全取代初始方法從而無法再使用初始方法。
總結(jié)
- 上一篇: HTML实现舔狗日记
- 下一篇: wincap的安装与环境配置