2010-01-22 68 views
22

可能重複:
How does an underscore in front of a variable in a cocoa objective-c class work?iPhone伊娃命名約定

我注意到,在很多參考資料在那裏,我看到了很多的時間,變數在.h文件被命名爲_variable,然後是@在.m文件synthesize'd爲

@synthesize variable = _variable; 

這是爲什麼呢?我錯過了什麼?

謝謝!

+0

我見過'ivar_'用於代替'_ivar'還可以,但我真的不能形成,除了他們看起來更好地爲他們的說法... – 2012-02-20 00:03:10

回答

21

沒有共識這個。有些人喜歡用它來清晰地分離出類變量,另一些人則指出避免與傳入參數名稱衝突。即使在Apple示例代碼中,使用也是混合的。

但是,我非常喜歡不使用_前綴,有兩個強有力的理由:

1)有些人認爲_是「私人」的良好指標。我的意思是,沒有一個類的局部變量應該訪問沒有一個setter/getter(屬性),因此他們都是私有的 - 爲什麼不命名他們更容易閱讀和使用自動完成?參數名稱中的任何重疊都會被編譯器快速顯示出來,並且可以通過對參數(或內部變量)的更周到的命名來避免。

2)(更好的理由) - 如果在XCode中對內部類var使用「重構」,其名稱與訪問它的屬性相同,則屬性和合成語句也將被重命名。如果對以_爲前綴的類變量使用重構,則不會更改屬性名稱 - 只是將內部名稱映射到合成映射。我幾乎不希望名稱因屬性不同而不同,從而暴露了它的訪問權限。僅憑這一點,我就不會希望使用_作爲變量前綴,因爲能夠改變名稱只是爲了提高代碼清晰度而做的最有用的事情。

+0

對命名方法參數的任何建議,使他們不與伊娃爾名稱衝突?對於initWith *或手動實現的屬性設置器來說,這尤其嚴重。 我已經試過「一/一個」和「新」的前綴一段時間,但它並不總是很方便(當一個名字是複數等)。 我也試着下劃線前綴參數,但是這是容易驅動代碼的讀者瘋狂,因爲蘋果和開發社區的喜好使用具有高德強調的。在某種程度上,這也適用於下劃線後綴。 – aleh 2014-03-28 14:40:52

+0

這些天,我用「\ _」的前綴爲所有內部類瓦爾(相反,我知道!),因爲我只用性能使用他們 - 因爲屬性自動創建的ivars _作爲前綴我堅持這一點。重構對屬性起作用,而屬性永遠不會看到名稱,因此「\ _」並不重要。它也消除了你有的重疊問題。我會編輯這個答案,以反映我在某個時候的新思想。 – 2014-03-28 15:28:06

+0

我明白了。我仍然個人猶豫通過屬性訪問我自己的ivars(例如更像_ivar/ivar vs self。ivar):不喜歡擁有公共可寫屬性或者將只讀屬性重新聲明爲在.m中可寫。但正如你所說,沒有共識:) – aleh 2014-03-31 09:44:15

1

這是純粹的約定。我想它的常見的,因爲當你一個getter方法調用是這樣的:

[myObject variable] 

你實際上是調用一個方法,而不是直接訪問的變量。前面的_表明你正在談論一個變量。就我個人而言,我覺得這種語法煩人和分心。我覺得沒有必要,但你是對的,它確實出現在這裏和那裏。

4

有時候人們使用mVarName(C++),而在Obj-c中,風格似乎是_varName。 你可以有一個問題,想象你的一個函數的參數是... set:(int)x - 但 - 你有一個名爲x的iVar ...好吧,你會讓編譯器哭這樣的東西 - 更不用說它的混亂。

m,_,無論幫助顯示什麼是類的成員屬性。

-(void) set:(int)x 
{ 
x = x; // x is an ivar! heh 
} 

VS

-(void) set:(int)x 
{ 
_x = x; // ahh I see! 
} 
15

使用語法是爲了更清楚的是,伊娃和財產是不同的東西的選項。

要在類的外部編碼,因爲它使用屬性沒有區別。

對於類本身的實現中的代碼,它可以使它更清楚何時使用ivar與屬性。

例如,假設我們有一個NSNumber對象伊娃/屬性:

@interface MyClass : NSObject { 
    NSNumber *num; 
} 
@property (nonatomic, retain) NSNumber *num; 
- (void)doSomething; 
@end 

@implementation MyClass 
@synthesize num; 

- (void)doSomething { 
    // set the property, num is properly retained 
    self.num = [NSNumber numberWithInteger:1]; 

    // accidentally set the ivar, num is NOT retained 
    num = [NSNumber numberWithInteger:2]; 
} 
@end 

現在使用不同的名稱爲伊娃和財產:

@interface MyClass : NSObject { 
    NSNumber *i_num; 
} 
@property (nonatomic, retain) NSNumber *num; 
- (void)doSomething; 
@end 

@implementation MyClass 
@synthesize num = i_num; 

- (void)doSomething { 
    // set the property, num is properly retained 
    self.num = [NSNumber numberWithInteger:1]; 

    // compiler error, there is no ivar named "num" 
    num = [NSNumber numberWithInteger:2]; 

    // set the ivar, so it needs to be a retained object 
    i_num = [[NSNumber alloc] initWithInteger:3]; 
} 
@end 
1

我不喜歡用「_」前綴,因爲蘋果並堅持使用它。通過避免前綴,我有更大的信心,當我擴展可可觸摸類時,我的ivars不會與Apple發生碰撞。由於我們無法訪問基類的源,所以這是我知道的避免意外重用現有私有ivars的唯一方法。

就像開頭

方法名「_」,單下劃線,保留給蘋果使用。

9

以前的答案是缺少這背後的歷史。在Objective-C 2.0之前,沒有任何屬性。所以,你必須與實例變量像這樣的對象:

@interface MyObject: NSObject { 
    NSArray *myArray; 
} 

@end 

但你怎麼會從其他對象訪問它們?解決方案是製作二傳手和獲得者。但是爲了避免混淆,他們會做這樣的:

@interface MyObject: NSObject { 
    NSArray *_myArray; 
} 

- (NSArray *)myArray; 
- (void)setMyArray:(NSArray *)myArray; 

@end 

_用於實例變量_myArray和方法-myArray之間清理混亂。

+0

我不知道如何保持沒有下劃線的伊娃名稱會與myArray方法名稱混淆。至少不是由編譯器。調用一個方法[obj myArray]或引用它的選擇器@selector(myArray)總是不同於引用它的ivar(obj-> myArray或簡單的myArray或self> myArray從自己的方法)。 – aleh 2014-03-28 14:29:38

+0

當你在一個類的實例方法中時,它更多。意外寫入'myArray = @ [@「A」,@「B」,@「C」];''而不是'myArray = @ [@「A」,@「B」,@「C」]; '。 – 2014-03-29 16:02:34

+0

好的,我明白了。我想你的意思是,當'self.myArray = ...'的含義時,錯誤輸入'myArray = ...'會更容易。 – aleh 2014-03-31 09:49:17

0

我的選擇,下面Google,簡直是追加下劃線,並明確地合成(即使我重新實現):

@synthesize varName=varName_; 

如果我看到結尾下劃線的init...dealloc的訪問之外,或者我知道有什麼可疑的。