关于C#:iPhone ivar命名约定

iPhone ivar naming convention

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
How does an underscore in front of a variable in a cocoa objective-c class work?

我注意到,在很多参考资料中,我看到很多时候,变量在.h文件中被命名为变量,然后在.m文件中被@synthesis'd命名为

1
@synthesize variable = _variable;

为什么要这样做?我错过了什么?

谢谢!


对此没有达成共识。有些人为了清晰起见喜欢使用它来分离类变量,正如另一个响应者注意到的那样,这样可以避免与传入的参数名冲突。即使在苹果示例代码中,使用也是混合的。

但是,我非常喜欢不使用_前缀,有两个强有力的原因:

1)有些人认为_是"私有"的一个很好的标志。我的看法是,没有setter/getter(属性)就不能访问类局部变量,因此它们都是私有的——既然这样,为什么不以一种更容易读取和使用autocomplete的方式命名它们呢?编译器会迅速发现参数名称中的任何重叠,并通过更贴心的参数(或内部变量)命名来避免重叠。

2)(更好的理由)-如果在Xcode中对内部类var使用"refactor",该内部类var与用于访问它的属性同名,则该属性和synthesis语句也将被重命名。如果在前缀为_的类变量上使用refactor,则不会更改属性名-只更改到内部名称的合成映射。我几乎不希望名称从属性到它公开访问的实际变量发生变化。单凭这一点,我就不想使用_作为变量前缀,因为能够转换名称是提高代码清晰度的最有用的方法。


使用该语法是一个选项,可以更清楚地说明ivar和属性是不同的。

对于类外部的代码,没有区别,因为它使用属性。

对于类本身实现中的代码,当使用ivar与属性进行比较时,可以更清楚地说明这一点。

例如,假设我们有一个nsnumber对象的ivar/属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@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

现在对ivar和属性使用不同的名称:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@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


以前的答案缺少这背后的历史。在目标C 2.0之前,没有任何特性。所以你会得到一个具有如下实例变量的对象:

1
2
3
4
5
@interface MyObject: NSObject {
    NSArray *myArray;
}

@end

但是您如何从其他对象访问它们呢?解决办法是制作setter和getter。但为了避免混淆,他们会这样做:

1
2
3
4
5
6
7
8
@interface MyObject: NSObject {
    NSArray *_myArray;
}

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

@end

_用于清除实例变量_myArray和方法-myArray之间的混淆。


有时人们使用MVARNEX(C++),而在Obj-C中,样式看起来是VALNEX。你能遇到的一个问题是,假设你对一个函数的参数是……set:(int)x-但是-你有一个名为x的ivar…好吧,你会让编译器为这样的事情大哭一场-更不用说它的混乱了。

m,u,无论什么都有助于显示类的成员属性。

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

VS

1
2
3
4
 -(void) set:(int)x
{
 _x = x; // ahh I see!
}

我不喜欢使用前缀,因为苹果一直使用它。通过避免使用前缀,我就有了更大的信心,当我扩展CocoaTouch类时,我的ivar不会与苹果的冲突。因为我们不能访问基类的源代码,所以这是我所知道的避免意外重用现有私有IVAR的唯一方法。

很像

Method names beginning with"_", a single underscore character, are reserved for use by Apple.


这纯粹是惯例。我认为这很常见,因为当您进行这样的方法getter调用时:

1
[myObject variable]

您实际上是在调用一个方法,而不是直接访问一个变量。前面的uu清楚地表明你在谈论一个变量。就我个人而言,我觉得这种句法很烦人,而且让人分心。我觉得这是不必要的,但你是对的,它确实出现在这里和那里。


我的偏好是,在google之后,只需添加下划线并显式合成(即使我正在重新实现):

1
@synthesize varName=varName_;

如果我看到init...dealloc或访问器外的尾随下划线,我知道有些东西可疑。