從C#到Objective-C,循序漸進學(xué)習(xí)蘋果開發(fā)(3)--分類(category)和協(xié)議Protocal的理解

本隨筆系列主要介紹從一個Windows平臺從事C#開發(fā)到Mac平臺蘋果開發(fā)的一系列感想和體驗歷程伞访,本系列文章是在起步階段逐步積累的,希望帶給大家更好式廷,更真實的轉(zhuǎn)換歷程體驗咐扭。本文繼續(xù)上一篇隨筆《從C#到Object C,循序漸進學(xué)習(xí)蘋果開發(fā)(2)--Objective-C和C#的差異》滑废,繼續(xù)對比介紹它們兩者之間的差異蝗肪,以便我們從C#陣營過來的人員加深印象,深入了解Objective-C語言的特性蠕趁。本篇隨筆主要針對Objective-C里面的分類(category)和協(xié)議Protocal概念的理解進行介紹薛闪。

1、分類(category)概念和使用

如果我們使用過C#俺陋,我們都知道豁延,C#里面有一個叫做擴展函數(shù)的東西,可以在不繼承已有類的情況下腊状,給存在的類增加一些原本沒有的接口函數(shù)诱咏,Objective-C的分類概念和這個很相似,甚至可以說是同一類型的東西缴挖,雖然不知道他們誰先誰后出現(xiàn)袋狞,這個東西的引入,能使得編程方面更加豐富高效映屋。
Objective-C提供了一種與眾不同的方式——Category苟鸯,可以動態(tài)的為已經(jīng)存在的類添加新的行為。這樣可以保證類的原始設(shè)計規(guī)模較小棚点,功能增加時再逐步擴展早处。使用Category對類進行擴展時,不需要訪問其源代碼瘫析,也不需要創(chuàng)建子類砌梆。Category使用簡單的方式默责,實現(xiàn)了類的相關(guān)方法的模塊化,把不同的類方法分配到不同的分類文件中么库。不過Category并不能給類擴展出屬性傻丝,這點要注意,因為Object C不支持這樣的屬性擴展诉儒。
分類(Category)的定義語法如下所示葡缰。

@interface ClassName (CategoryName)
 
@end

這里好像它們還有一個約定俗成的習(xí)慣,將聲明文件和實現(xiàn)文件名稱統(tǒng)一采用“原類名+Category”的方式命名忱反。所以O(shè)C的這種功能雖然和C#功能差不多泛释,但是這點約定和C#不一樣,C#不管你放到哪里都行温算,但是我們還是會應(yīng)該尊重它的規(guī)則怜校。

例如,我們給XYZPerson類增加一個擴展方法的定義如下所示注竿,這個定義的函數(shù)約定是放到文件"XYZPerson+XYZPersonNameDisplayAdditions.h"里面茄茁。

#import "XYZPerson.h"
 
@interface XYZPerson (XYZPersonNameDisplayAdditions)
- (NSString *)testMethod;
@end

那么它的實現(xiàn)代碼如下所示,它的代碼約定是放到 "XYZPerson+XYZPersonNameDisplayAdditions.m"里面巩割。

#import "XYZPerson+XYZPersonNameDisplayAdditions.h"
 
@implementation XYZPerson (XYZPersonNameDisplayAdditions)
- (NSString *)testMethod {
    return [NSString stringWithFormat:@"%@, %@", self.lastName, self.firstName];
}
@end

在C#里面裙顽,擴展方法是命名空間相關(guān)的,一旦跳出了命名空間的范圍宣谈,這個擴展函數(shù)就不在起作用愈犹,而Objective-C的這個和類一樣,沒有命名空間的概念闻丑,因此在擴展的時候漩怎,需要小心謹(jǐn)慎一點,否則容易導(dǎo)致分類的接口和類本身發(fā)生沖突嗦嗡⊙福基于這個原因,所以蘋果建議也是給分類的接口增加一個前綴侥祭,命名則采用接口的一貫規(guī)則叁执,如下面代碼所示。

@interface NSSortDescriptor (XYZAdditions)
+ (id)xyz_sortDescriptorWithKey:(NSString *)key ascending:(BOOL)ascending;
@end

這樣擴展方法名稱雖然長了一點卑硫,但是基本上確保和普通的接口方法不會發(fā)生沖突了。
Category的使用場景:
1蚕断、當(dāng)你在定義類的時候欢伏,在某些情況下(例如需求變更),你可能想要為其中的某個或幾個類中添加方法亿乳。
2硝拧、一個類中包含了許多不同的方法需要實現(xiàn)径筏,而這些方法需要不同團隊的成員實現(xiàn)
3、當(dāng)你在使用基礎(chǔ)類庫中的類時障陶,你可能希望這些類實現(xiàn)一些你需要的方法滋恬。

遇到以上這些需求,Category可以幫助你解決問題抱究。當(dāng)然恢氯,使用Category也有些問題需要注意,
1鼓寺、Category可以訪問原始類的實例變量勋拟,但不能添加變量,如果想添加變量妈候,可以考慮通過繼承創(chuàng)建子類敢靡。
2、Category可以重載原始類的方法苦银,但不推薦這么做啸胧,這么做的后果是你再也不能訪問原來的方法。如果確實要重載幔虏,正確的選擇是創(chuàng)建子類纺念。
3、和普通接口有所區(qū)別的是所计,在分類的實現(xiàn)文件中可以不必實現(xiàn)所有聲明的方法柠辞,只要你不去調(diào)用它。
還有一種成為類擴展的功能主胧,它是針對存在代碼的類的情況叭首,也就是你的類代碼和你擴展的源碼是同時編譯的情況下。
類擴展的方法和上面的分類類似踪栋,他們不需要寫擴展分類的名稱焙格,這個有點像匿名擴展分類的概念了,如下所示

@interface ClassName ()
 
@end

這個匿名的擴展分類夷都,和普通的Category不同眷唉,它除了可以方法外,還可以添加屬性或者變量的囤官。

2冬阳、協(xié)議Protocal

這個概念有很大程度上和C#的接口類似,但是它有所不同党饮,它可以可選的實現(xiàn)接口@optional肝陪,也有必選的實現(xiàn)接口@required,雖然Objective-C里面已經(jīng)有一個關(guān)鍵字 @interface刑顺,不過這個和Protocal還是有不同的氯窍。
和C#的接口一樣饲常,這種協(xié)議也可以繼承自另外一個Protocal,也就是他們可以有繼承關(guān)系狼讨。

@protocol NewProtocal <Protocal>
@end

由于Objective-C開發(fā)的很多應(yīng)用贝淤,如IOS的應(yīng)用,他們在MVC的開發(fā)模型里面政供,都大量使用了代理模式播聪,這種Protocal很好的處理了這種關(guān)系。在iOS和OS X開發(fā)中鲫骗,Apple采用了大量的代理模式來實現(xiàn)MVC中View和Controller的解耦犬耻。
例如UIView產(chǎn)生的所有事件,都是通過委托的方式交給Controller完成执泰。根據(jù)約定枕磁,框架中后綴為Delegate的都是Protocol,例如UIApplicationDelegate术吝,UIWebViewDelegate等计济。
在C#里面有很多如IClonable, IEnumerable這樣的接口,只要實現(xiàn)了排苍,就能實現(xiàn)克隆和枚舉沦寂,在Objective-C里面,這個就是可以使用Protocal來替代了淘衙,如果某個協(xié)議繼承了NSObject传藏,那么這是代表在此聲明的協(xié)議,是NSObject協(xié)議的衍生協(xié)議(不是NSObject類)彤守,也就是說毯侦,這里的語境理解NSObject是一個協(xié)議,如果是在@Interface里面的繼承關(guān)系具垫,那么那個就是NSObject對象侈离。有點意思哦。
下面是一個可選和必選的協(xié)議定義例子筝蚕。

@protocol XYZPieChartViewDataSource
- (NSUInteger)numberOfSegments;
- (CGFloat)sizeOfSegmentAtIndex:(NSUInteger)segmentIndex;
@optional
- (NSString *)titleForSegmentAtIndex:(NSUInteger)segmentIndex;
- (BOOL)shouldExplodeSegmentAtIndex:(NSUInteger)segmentIndex;
@required
- (UIColor *)colorForSegmentAtIndex:(NSUInteger)segmentIndex;
@end

由于協(xié)議有可選和必選卦碾,如果我們想知道某個動態(tài)的對象是否具有某個接口函數(shù),就是通過@selector操作符來進行判斷的起宽。

NSString *thisSegmentTitle;
    if ([self.dataSource respondsToSelector:@selector(titleForSegmentAtIndex:)]) {
        thisSegmentTitle = [self.dataSource titleForSegmentAtIndex:index];
    }

和C#的接口定義類似洲胖,Objective-C的一個類對象它可以實現(xiàn)多的協(xié)議,如下例子是一個類的接口定義實現(xiàn)幾個協(xié)議的情況坯沪。

@interface MyClass : NSObject <MyProtocol, AnotherProtocol, YetAnotherProtocol>
...
@end

這樣就實現(xiàn)了MyClass對象只有一個基類對象绿映,但是可以實現(xiàn)多個協(xié)議(C#是多個接口)的情況。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末屏箍,一起剝皮案震驚了整個濱河市绘梦,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌赴魁,老刑警劉巖卸奉,帶你破解...
    沈念sama閱讀 222,946評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異颖御,居然都是意外死亡榄棵,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評論 3 399
  • 文/潘曉璐 我一進店門潘拱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來疹鳄,“玉大人,你說我怎么就攤上這事芦岂”窆” “怎么了?”我有些...
    開封第一講書人閱讀 169,716評論 0 364
  • 文/不壞的土叔 我叫張陵禽最,是天一觀的道長腺怯。 經(jīng)常有香客問我,道長川无,這世上最難降的妖魔是什么呛占? 我笑而不...
    開封第一講書人閱讀 60,222評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮懦趋,結(jié)果婚禮上晾虑,老公的妹妹穿的比我還像新娘。我一直安慰自己仅叫,他們只是感情好帜篇,可當(dāng)我...
    茶點故事閱讀 69,223評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著惑芭,像睡著了一般坠狡。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上遂跟,一...
    開封第一講書人閱讀 52,807評論 1 314
  • 那天逃沿,我揣著相機與錄音,去河邊找鬼幻锁。 笑死凯亮,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的哄尔。 我是一名探鬼主播假消,決...
    沈念sama閱讀 41,235評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼岭接!你這毒婦竟也來了富拗?” 一聲冷哼從身側(cè)響起臼予,我...
    開封第一講書人閱讀 40,189評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎啃沪,沒想到半個月后粘拾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,712評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡创千,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,775評論 3 343
  • 正文 我和宋清朗相戀三年缰雇,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片追驴。...
    茶點故事閱讀 40,926評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡械哟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出殿雪,到底是詐尸還是另有隱情暇咆,我是刑警寧澤,帶...
    沈念sama閱讀 36,580評論 5 351
  • 正文 年R本政府宣布丙曙,位于F島的核電站糯崎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏河泳。R本人自食惡果不足惜沃呢,卻給世界環(huán)境...
    茶點故事閱讀 42,259評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望拆挥。 院中可真熱鬧薄霜,春花似錦、人聲如沸纸兔。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽汉矿。三九已至崎坊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間洲拇,已是汗流浹背奈揍。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留赋续,地道東北人男翰。 一個月前我還...
    沈念sama閱讀 49,368評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像纽乱,于是被迫代替她去往敵國和親蛾绎。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,930評論 2 361

推薦閱讀更多精彩內(nèi)容