2011-04-16 33 views
14

類可以在目標C使用類如被擴展:Objective-C類別名稱可以做什麼嗎?

@interface NSString (CategoryName) 
-(NSString *)myFabulousAddition; // a fabulous additional method 
@end 

///////////////////////////// 
@implementation NSString (CategoryName) 

-(NSString *)myFabulousAddition { 
    // do something fabulous... 

} 
@end 

在該小例子,我會被添加方法myFabulousAddition到的NSString。我可以通過[anNSString myFabulousAddition]來調用它,就像它是NSString方法集的一部分一樣。偉大而有用。

Apple documents regarding Categories,該文檔的狀態:

有沒有限制的 類別,你可以添加到 類的數量,但每個類別名稱必須 不同,各自應申報和 定義了一組不同的方法。

如果你有這樣的事情:

@interface NSString (CategoryName) 
-(NSString *)myFabulousAddition; // a fabulous additional method 
@end 

@interface NSString (ANOTHERCategoryName) 
-(NSString *)myFabulousAddition; // a DIFFERENT fabulous additional method 
            // BUT with same name as the other category 
@end 


///////////////////////////// 

@implementation NSString (CategoryName) 

-(NSString *)myFabulousAddition { 
    // do something fabulous... 

} 
@end 
@implementation NSString (ANOTHERCategoryName) 

-(NSString *)myFabulousAddition { 
    // do something equally fabulous, but DIFFERENT... 

} 
@end 

缺乏在括號名稱的表示形式是一個擴展類,如下所示:

@interface MyObject() // No name -- an extension vs category to MyObject 
- (void)setNumber:(NSNumber *)newNumber; 
@end 

類別名稱對編譯器或鏈接器有任何意義嗎?無論如何,類別名稱是方法簽名的一部分嗎?還是它是原始名稱空間的一部分?如果類別名稱沒有意義,你怎麼知道你是否要踩另一種方法並得到未定義的行爲?

回答

6

避免方法跺腳的方法是前綴您的類別方法名,這樣的:如果你從不同類別的方法名稱的衝突,那麼其中一個「贏」在運行時

@interface NSString (MyCompanyCategoryName) 

- (NSString *)MYCO_fabulousAddition; 

@end 

是完全未定義的。

類別的名稱幾乎完全沒用,除了名稱類別(即())是爲類擴展保留的。類擴展的方法應該在類主@implementation中實現。

+2

似乎我唯一的保護是'SomeUniquePrefixForMyCompanyOrMeThatIsUglyFabulousMethod'這只是增加了我可憐的手指重複應激綜合徵...謝謝! – 2011-04-16 19:56:49

+0

而實際上添加前綴到您使用的是類添加方法,還建議由蘋果... – Moszi 2011-04-16 20:05:57

+1

@蘿蔔頂,如果Xcode中沒有提供代碼完成,這將是真實的。 – 2011-04-18 08:19:49

1

行爲(很大程度上)是不可預測的 - 其中一個類別將勝出,但您無法確定哪一個類別。另外,我認爲你很可能會從一個實現開始,並最終得到另一個(如果第二個類在第一個之後加載)。

+1

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocCategories.html%23//apple_ref/doc/uid/TP30001163-CH20-SW1 says「A framework您嘗試重寫的定義的方法本身可能已在類別中實現,因此沒有定義哪個實現優先。「 – 2011-04-16 19:46:53

3

類別名稱並不意味着什麼特別的東西,它只是一個標識符。除非鏈接器(或運行時加載器)決定給你一個警告,否則無法判斷多個類別是否定義了相同的方法。

0

我相信他們沒有任何意義。你不會在你的代碼中真正使用它們......因爲它們是類別和......類別的語義......只是對某些東西進行分類,我認爲這有些合乎邏輯...... 我會說他們只是簡單地收集方法...

另一方面,你的問題是非常有效的......你不知道你是否重寫一個方法。如果你在同一個項目中,那麼編譯器發出警告(或者錯誤,我不記得),但是如果你從庫中重寫一個方法,那麼......你運氣不好......

+0

我的擔心是無意中更重於第三方庫的方法。比方說,我添加了一個第三方或開源代碼,將「trim」添加到NSString中。那麼我也在我的NSString工具箱裏有'trim'。我們將要使用的「trim」是誰?未定義,沒有警告...... Grrrr。 – 2011-04-16 19:55:59

+0

不幸的是,Objective-C中有一個名稱空間,這迫使第三方庫的開發者玩遊戲,像添加前綴到他們的類別,他們希望將(和仍然)是獨一無二的。我用我的首字母加下劃線並希望最好(如Objective-C很快就會獲得多個名稱空間)。 – Rayfleck 2011-04-16 19:59:05

+0

是的。未定義...我不喜歡這種行爲... – Moszi 2011-04-16 20:01:22

1

它當然充當標識符,從程序員的點。在編譯器的視角中,類別方法只是作爲類的擴展(從中擴展)添加,而不管名稱如何。

是的,你可以添加同一類的類具有相同的標識符,即使有相同的功能。但是你絕對不能重寫任何函數,因爲一旦你定義了類,類只是類的一部分(就像你無法在該類中覆蓋類的函數一樣)。

,因爲它們是在運行時被添加,他們沒有提出任何錯誤,只有在運行時編譯器選擇功能,這是完全不可預測的。

相關問題