你如何命名实例/参数值?

时间:2008-08-13 20:03:54

标签: objective-c cocoa

成为Objective-C(但是长期的C / ++)程序员的新手我正在寻找有关变量命名约定的建议/建议。

我个人的偏好是为实例中的清晰度使用前缀作为实例变量,并防止功能参数的阴影。然而,我是排除前缀的属性的粉丝(除非你也为你的属性名称添加前缀,这不是很好,看起来很糟糕)。同样地,我可以使用“self.variable”约定,但前提是我将一切都设为属性。

所以给定下面的代码你的首选实例/函数变量的命名风格是什么?如果你不打扰,你如何处理函数参数的阴影?

@interface GridItem : NSObject
{
    CGRect _rect;
    ...  
}
@end

-(void) initFromRect:(CGRect)rect
{
    _rect = rect;
    ...
}

干杯!

10 个答案:

答案 0 :(得分:15)

大多数Cocoa项目使用underbar作为非IBOutlet实例变量前缀,并且对IBOutlet实例变量不使用前缀。

我不为IBOutlet实例变量使用下划线的原因是,当加载nib文件时,如果你有一个连接插座的setter方法,那么将调用该setter。 然而此机制使用键值编码,因此IBOutlet的名称前缀为下划线(例如 _myField将被设置,除非设置器的名称与插座完全相同(例如 set_myField:),这是非标准和粗略的。

另外,请注意,使用self.myProp等属性 与访问实例变量相同。您在使用属性时发送消息,就像使用[self myProp]之类的括号表示法一样。所有属性都为您提供了一个简洁的语法,用于在一行中指定getter和setter,并允许您合成它们的实现;它们实际上并没有使消息调度机制短路。如果要直接访问实例变量,但在其前面添加self,则需要将self视为指针,如self->myProp,这实际上是C风格的字段访问。

最后,在编写Cocoa代码时不要使用匈牙利符号,并回避其他前缀如“f”和“m_” - 这会将代码标记为由没有“得到它”的人编写并且将会导致它被其他Cocoa开发者怀疑。

一般情况下,请遵循Coding Guidelines for CocoaApple Developer Connection文档中的建议,其他开发人员将能够接收并理解您的代码,并且您的代码将适用于所有Cocoa使用运行时内省的功能。

以下是使用我的约定的窗口控制器类的样子:

// EmployeeWindowController.h
#import <AppKit/NSWindowController.h>

@interface EmployeeWindowController : NSWindowController {
@private
    // model object this window is presenting
    Employee *_employee;

    // outlets connected to views in the window
    IBOutlet NSTextField *nameField;
    IBOutlet NSTextField *titleField;
}

- (id)initWithEmployee:(Employee *)employee;

@property(readwrite, retain) Employee *employee;

@end

// EmployeeWindowController.m
#import "EmployeeWindowController.h"

@implementation EmployeeWindowController

@synthesize employee = _employee;

- (id)initWithEmployee:(Employee *)employee {
    if (self = [super initWithWindowNibName:@"Employee"]) {
        _employee = [employee retain];
    }
    return self;
}

- (void)dealloc {
    [_employee release];

    [super dealloc];
}

- (void)windowDidLoad {
    // populates the window's controls, not necessary if using bindings
    [nameField setStringValue:self.employee.name];
    [titleField setStringValue:self.employee.title];
}

@end

你会看到我在我的Employee-init方法中直接使用引用-dealloc的实例变量,而我在其他方法中使用该属性。这通常是一个带有属性的好模式:只需触摸初始值设定项中的属性的基础实例变量,-dealloc以及属性的getter和setter。

答案 1 :(得分:8)

我遵循Chris Hanson关于下划线ivar前缀的建议,但我承认我也使用下划线来表示IBOutlets。但是,我最近开始根据@mmalc's suggestionIBOutlet声明移至@property行。好处是我的所有ivars现在都有一个下划线和标准的KVC设置器(即setNameField:)。此外,插座名称在Interface Builder中没有下划线。

@interface EmployeeWindowController : NSWindowController {
@private
    // model object this window is presenting
    Employee *_employee;

    // outlets connected to views in the window
    NSTextField *_nameField;
    NSTextField *_titleField;
}

- (id)initWithEmployee:(Employee *)employee;

@property(readwrite, retain) Employee *employee;
@property(nonatomic, retain) IBOutlet NSTextField *nameField;
@property(nonatomic, retain) IBOutlet NSTextField *titleField;

@end

答案 2 :(得分:3)

您可以在ivars上使用下划线前缀,并仍然使用非下划线名称作为属性。对于合成访问器,只需执行以下操作:

@synthesize foo = _foo;

这告诉编译器使用the_foo ivar合成foo属性。

如果您编写自己的访问者,那么您只需在实现中使用underbar ivar并保留非underbar方法名称。

答案 3 :(得分:2)

就个人而言,我遵循Cocoa命名约定,使用驼峰套管作为函数和变量,并使用驼峰套管作为对象名称(当然没有前导NS)。

我发现类型前缀使得代码对于没有编写代码的人来说更加不透明(因为每个人总是使用不同的前缀),而在现代IDE中,找出某些类型并不是那么困难。

答案 4 :(得分:2)

随着属性的引入,我认为不需要在类实例变量前加上“_”。您可以设置一个简单的规则(在头文件中描述),必须通过属性访问要在类外部访问的任何变量,或者使用类上的自定义方法来影响值。这对我来说似乎比在他们的前面贴着“_”的名字要清晰得多。它还可以正确封装值,以便您可以控制它们的更改方式。

答案 5 :(得分:1)

除了这里所说的内容之外,请务必阅读关于Key Value Observing兼容命名的Cocoa文档。从长远来看,严格遵循这种模式将对您有很大帮助。

答案 6 :(得分:1)

我的风格是混合动力,真的是PowerPlant时代的延续:

我使用的最有用的前缀是函数/方法参数的“in”和“out”。这有助于您一目了然地了解参数,并确实有助于防止方法参数和实例变量之间的冲突(有多少次您看到参数“table”与同名的实例变量冲突)。 E.g:

- (void)doSomethingWith:(id)inSomeObject error:(NSError **)outError;

然后我使用裸名称作为实例变量和属性名称:

然后我使用“the”作为局部变量的前缀:theTable,theURL等。再次,这有助于区分本地变量和实例变量。

然后按照PowerPlant样式我使用了一些其他前缀:k代表常量,E代表枚举,g代表全局,s代表静态。

我一直在使用这种风格已有12年了。

答案 7 :(得分:1)

我不喜欢使用下划线作为任何标识符的前缀,因为C和C ++都保留了某些下划线前缀供实现使用。

我认为使用“self.variable”是丑陋的。

通常,我对实例变量使用未加修饰的标识符(即没有前缀或后缀)。如果你的课程如此复杂以至于你无法记住实例变量,那你就麻烦了。因此,对于您的示例,我将使用“rect”作为实例变量的名称,并使用“newRect”或“aRect”作为参数名称。

答案 8 :(得分:1)

虽然我喜欢在ivars中使用下划线前缀,但我不喜欢写@synthesize行因为所有重复(它不是很DRY)。我创建了一个宏来帮助完成这个并减少代码重复。因此,而不是:

@synthesize employee = _employee;

我写这个:

ddsynthesize(employee);

这是一个简单的宏,使用令牌粘贴在右侧添加下划线:

#define ddsynthesize(_X_) @synthesize _X_ = _##_X_

唯一的缺点是它会混淆Xcode的重构工具,如果你通过重构重命名该属性,它将不会被重命名。

答案 9 :(得分:1)

Andrew:实际上有很多Cocoa开发人员根本不使用实例变量前缀。它在Smalltalk世界中也非常普遍(事实上,我认为在Smalltalk中几乎闻所未闻的是在实例变量上使用前缀)。

实例变量的前缀总是让我感到震惊,因为C ++ - ism被带到了Java,然后被带到了C#。由于Objective-C世界在很大程度上与C ++世界平行,因为Java和C#世界是它的继承者,这可以解释您在不同的开发人员之间可能会看到的“文化”差异。