簡體   English   中英

Objective C中的實例變量/方法參數命名

[英]instance variable/ method argument naming in Objective C

以下人們對實例變量和方法參數的命名有什么約定 - 特別是當使用方法參數來設置ivars(實例變量)時?

在C ++中,我過去常常使用iv_的m_前綴。 在C#中,我遵循了純粹使用this.方法消除歧義的慣例this. 對於伊娃。 我已經采用了C ++中的等價物( this-> )。

在目標C中我嘗試了一些事情,但沒有一個真的令人滿意。

除非有人建議一些非常好的東西,否則我將不得不妥協(但請不要讓我使用args the前綴!),所以我很想聽聽大多數人說的話 - 特別是來自那些一直使用ObjC的人。

在發布這個之前我做了一些盡職調查,並且發現了一些很好的資源:

他們給了我一些想法,但我仍然渴望聽到別人在做什么。

[編輯]只是為了澄清:這是你如何區分ivars和我正在尋找的方法args - 無論是通過前綴還是其他技術。

[編輯2]感謝所有的回復和討論要點。 我不會在我的評論結束這一點,而只是說,我指出接受的答案,我已經用前綴初始化ARGS與公約the (與和setter ARGS new ,這是我在做什么反正) 。 這似乎是力量的最佳平衡 - 即使我自己並不熱衷於審美。

正如您所指出的,如果參數名稱與實例變量沖突,Cocoa樣式將使用方法參數名稱,如theValue 然而,在Objective-C 2.0樣式代碼中出現這種情況不應該多次。 假設你不應該(通常)直接訪問實例變量。 這主要是因為這樣做可以繞過Cocoa中的Key-Value Observing機制。 相反,期望您將通過getter / setter方法訪問和改變屬性。 在Objective-C 2.0中,很容易聲明這些屬性並自動@synthesize getter / setter,所以沒有多少借口不使用它們。 事實上,在64位系統上,運行時將自動為您創建實例變量,從而無需聲明它們並減少使用它們的沖動。

您應該直接訪問實例變量的唯一時間是-init-dealloc方法:

@interface MyObject : NSObject 
{
  id ivar;
}

@property (retain,readwrite) id ivar; //or whatever retain/copy/assign and read/readwrite makes sense
@end

@implementation MyObject
@synthesize ivar;

- (id)initWithIvar:(id)theIvar {
  if(self = [super init]) {
    ivar = theIvar;
  }

  return self;
}

- (void)dealloc {
  [ivar release];
}

在這些情況下應該直接使用ivar的原因是因為getter / setter可能具有依賴於完全初始化的實例的副作用,因此在-init-dealloc它們變得危險,其中對象的狀態被完全初始化。 在所有其他情況下,您應該使用self.ivar (或[self ivar][self setIvar:newValue] )。

似乎除-initWithXX之外的方法不應該具有命名沖突。 如果他們這樣做,他們不應該重構沒有那個參數或者Class沒有實例變量嗎?

這只留下-initWithXX方法,您經常會在參數和ivars之間發現沖突。 對於這種情況,如果你真的無法忍受Cocoa風格,你可以使用你提到的任何方法。 使用_作為前綴並且相對常見(我相信@synthesize的設置器和getter將在這種情況下自動執行正確的操作,但您可能必須明確地將_ivar設置為支持)。

這就是Apple如何做到的

要完成所有已知的Objective-C樣式指針,請訪問 Google版本。 他們所做的是在成員varname之后添加下划線。 比如BOOL isActive_;
所以做出選擇並堅持下去。 我也更喜歡我的應用程序的“_”前綴。

Obj-C沒有像許多其他語言那樣嚴格定義“樣式”,這可能是一件好事,或者說是一件壞事,但這意味着你可以在大多數時間內找到一個好的編碼風格。

您還可以通過self訪問Obj-C中的變量。 因此,如果您有一個實例變量測試,您可以通過self-> test訪問它,這是合法的並且將始終有效。 然而,在大多數Obj-C程序員看來,它並不美觀。 它給出了“秘密”,對象實際上只是結構(更准確地說,對象引用是結構的指針),實例變量實際上是結構成員。 並不是說這是真的秘密,但是Obj-C程序員似乎更喜歡在他們的代碼中“隱藏”這個事實。

在名稱中使用下划線“_”是一個非常糟糕的主意。 這里有人指出,Apple為其代碼保留了下划線,但實際上GCC已經為符號名稱保留了下划線。 更確切地說,ANSI-C標准已經規定,以兩個下划線或一個下划線和大寫字母開頭的變量是為編譯器的內部用法保留的。 所以使用一個下划線在理論上是有效的,但是不小心用大寫字母開始這個名字,它變得無效。

到目前為止我嘗試使用前綴my,myName而不是name,並使用self,selfName而不是name; 起初看起來有些奇怪,但在一大段代碼中看起來並不太糟糕。 至少立即擊中眼睛“不同”。 我也只是嘗試了一個“i”,iName而不是名字(或iname而不是name),但我對這個解決方案並不是很滿意。

不過,我從不浪費時間考慮方法參數。 因為它並不重要。 這些變量與任何其他變量一樣,除非它們被聲明為常量。 它們甚至可以在方法中重復用於其他目的,因為它對調用者沒有任何影響。 例如

- (NSImage *)loadImage:(int)imageNumber
{
  NSImage * res;

  // Some code that assigns a value to res
  // ...  

  // Re-use imageNumber for a different purpose
  for (imageNumber = 0; ...; ...) {
     // Some code
  }

  return res;
}

我發現該代碼沒有問題。 為什么我必須為此聲明第二個堆棧變量,只要名稱仍然有意義(如果我沒有在for循環中按照數字迭代圖像,那么這個名稱當然沒有意義,在這種情況下我會使用一個不同的變量 - 編譯器實際上可以在堆棧上只為一個保留一個int)。

Apple生成的示例代碼通常使用“_”前綴。 我想我也看到一些使用mFoom_foo 有些人根本不打擾前綴,只是使用普通名稱,但后來會讓人感到困惑。 通常,在定義方法參數時,命名約定是使用“a”,“an”,“the”或“new”前綴。 例如:

@interface Foo : NSObject {
    id _bar;
}
@property (nonatomic, retain) id bar;

- (id) initWithBar:(id)aBar;

@end

@implementation Foo
@synthesize bar = _bar;

- (id) initWithBar:(id)aBar {
    self = [super init];
    if(self != nil) {
        _bar = aBar;
    }
    return self;
}

@end

我發現這個慣例很有效。 我曾經不打擾前綴,但有時讓事情變得混亂。 使用前綴清楚地表明它是一個實例變量。 Apple在其(iPhone)示例代碼中使用@synthesize bar = _bar約定。

實際上通常不會使用實例變量,所以如果你發現“_”前綴很煩人並不重要,因為你會使用[self bar] (如果你是那種東西的話,還是self.bar )無論如何。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM