【问题标题】:iPhone ivar naming convention [duplicate]iPhone ivar 命名约定 [重复]
【发布时间】:2011-01-08 01:06:42
【问题描述】:

可能重复:
How does an underscore in front of a variable in a cocoa objective-c class work?

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

@synthesize variable = _variable;

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

谢谢!

【问题讨论】:

  • 我也看到ivar_ 被用来代替_ivar,但我真的无法为它们形成论据,除非它们看起来更好......

标签: iphone objective-c


【解决方案1】:

对此没有共识。为了清晰起见,有些人喜欢使用它来分离类变量,并且正如另一个响应者指出的那样,以避免与传入的参数名称发生冲突。即使在 Apple 示例代码中,用途也是混杂的。

但是,我非常喜欢不使用 _ 前缀,并且有两个强有力的理由:

1) 有人认为_ 是“私人”的一个很好的指标。我的看法是,不应该在没有 setter/getter(属性)的情况下访问任何类局部变量,因此它们都是私有的——考虑到为什么不以更容易阅读和使用自动完成的方式命名它们呢?编译器会很快发现参数名称中的任何重叠,并通过对参数(或内部变量)进行更深思熟虑的命名来避免。

2)(更好的理由)- 如果您在 XCode 中对与用于访问它的属性命名相同的内部类 var 使用“重构”,则属性和综合语句也将被重命名。如果您对前缀为 _ 的类变量使用重构,则不会更改属性名称 - 只是合成映射到内部名称。我几乎从不希望名称从属性变为它公开访问的真实变量。仅这一点就让我永远不想使用 _ 作为变量前缀,因为能够转换名称几乎是提高代码清晰度的最有用的事情。

【讨论】:

  • 关于命名方法参数的任何建议,以免它们与 ivar 名称冲突?这对于 initWith* 或手动实现的属性设置器尤其严重。我已经尝试了一段时间的“a/an”和“new”前缀,但这并不总是很方便(比如当一个名字是复数时)。我也尝试过为参数添加下划线前缀,但这很容易让代码阅读者发疯,因为 Apple 和开发者社区偏好将下划线与 ivars 一起使用。在某种程度上,这也适用于下划线后缀。
  • 这些天我为所有内部类变量使用“_”前缀(我知道相反!)因为我只将它们与属性一起使用——并且由于属性会自动创建 iVar,并以 _ 作为我坚持的前缀那。重构适用于属性,而对于属性,您永远不会看到名称,因此“_”并不重要。它还消除了您遇到的重叠问题。我会编辑这个答案以反映我的新想法。
  • 我明白了。我个人仍然对通过属性访问我自己的 ivars 犹豫不决(例如,更像 _ivar/ivar 与 self.ivar):不喜欢拥有公共可写属性或将只读属性重新声明为在 .m 中可写。但正如你所说,没有共识:)
【解决方案2】:

使用该语法可以更清楚地表明 ivar 和属性是不同的东西。

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

对于类本身实现中的代码,使用ivar和property可以更清楚。

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

@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 和属性使用不同的名称:

@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

【讨论】:

    【解决方案3】:

    以前的答案缺少这背后的历史。在 Objective-C 2.0 之前,没有属性。因此,您将拥有一个具有如下实例变量的对象:

    @interface MyObject: NSObject {
        NSArray *myArray;
    }
    
    @end
    

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

    @interface MyObject: NSObject {
        NSArray *_myArray;
    }
    
    - (NSArray *)myArray;
    - (void)setMyArray:(NSArray *)myArray;
    
    @end
    

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

    【讨论】:

    • 我不确定如何将不带下划线的 ivar 名称与 myArray 方法名称混淆。至少不是由编译器。调用方法 [obj myArray] 或引用它的选择器 @selector(myArray) 总是不同于引用它的 ivar(obj->myArray 或简单地 myArray 或 self->myArray 来自自己的方法)。
    • 当你在一个类的实例方法中时更是如此。很容易不小心写成myArray = @[@"A", @"B", @"C"]; 而不是myArray = @[@"A", @"B", @"C"];
    • 好的,我明白了。我猜你的意思是说myArray = ... 的意思是self.myArray = ... 时更容易打错。
    【解决方案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!
    }
    

    【讨论】:

      【解决方案5】:

      这纯粹是约定俗成的。我想它很常见,因为当你像这样进行方法 getter 调用时:

      [myObject variable]
      

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

      【讨论】:

        【解决方案6】:

        我不喜欢使用“_”前缀,因为 Apple 一直使用它。通过避免前缀,我更有信心在扩展可可触摸类时我的 ivars 不会与 Apple 冲突。由于我们无法访问基类的源代码,这确实是我所知道的避免意外重用现有私有 ivars 的唯一方法。

        很像

        以“_”(一个下划线字符)开头的方法名称保留供 Apple 使用。

        【讨论】:

          【解决方案7】:

          Google 之后,我的偏好是简单地附加一个下划线并显式合成(即使我正在重新实现):

          @synthesize varName=varName_;
          

          如果我在init...dealloc 或访问器之外看到尾随下划线,我就知道有些东西有问题。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2011-05-14
            • 2016-07-22
            • 2014-10-24
            • 1970-01-01
            • 1970-01-01
            • 2010-10-13
            • 1970-01-01
            • 2014-11-27
            相关资源
            最近更新 更多