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

我个人的偏好是对实例变量使用前缀,既是为了函数内的清晰性,也是为了防止函数参数的隐藏。不过,我很喜欢排除前缀的属性(除非您也为属性名称添加前缀,这效果不太好而且看起来很愚蠢)。同样,我可以使用“self.variable”约定,但前提是我将所有内容都设为属性。

那么,考虑到下面的代码,您首选的实例/函数变量命名风格是什么?如果您不介意的话,您如何处理函数参数的阴影?

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

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

干杯!

有帮助吗?

解决方案

大多数 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 开发人员的怀疑。

一般来说,请遵循以下建议 Cocoa 编码指南 文档位于 苹果开发者连接, ,其他开发人员将能够拿起并理解您的代码,并且您的代码将与使用运行时自省的所有 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 中。

其他提示

我遵循 Chris Hanson 关于下划线 ivar 前缀的建议,尽管我承认我也将下划线用于 IBOutlet。然而,我最近开始移动我的 IBOutlet 声明给 @property 线,按照 @mmalc的建议. 。好处是我的所有 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

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

@synthesize foo = _foo;

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

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

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

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

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

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

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

一般来说,我对实例变量使用朴素的标识符(即没有前缀或后缀)。如果你的类太复杂以至于你记不住实例变量,那么你就有麻烦了。因此,对于您的示例,我将使用“rect”作为实例变量的名称,并使用“newRect”或“aRect”作为参数名称。

安德鲁:实际上有很多 Cocoa 开发人员根本不使用实例变量前缀。这在 Smalltalk 世界中也非常常见(事实上,我想说在 Smalltalk 中在实例变量上使用前缀几乎是闻所未闻的)。

实例变量的前缀总是让我觉得这是一种 C++ 主义,它被引入了 Java,然后又引入了 C#。由于 Objective-C 世界在很大程度上与 C++ 世界平行,而 Java 和 C# 世界是它的后继者,这可以解释您可能会在不同开发人员群体之间看到的“文化”差异。

我的风格是混合风格,实际上是 PowerPlant 时代的延续:

我使用的最有用的前缀是函数/方法参数的“in”和“out”。这可以帮助您一目了然地知道参数的用途,并且确实有助于防止方法参数和实例变量之间的冲突(您见过多少次参数“表”与同名实例变量冲突)。例如。:

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

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

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

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

我已经使用这种风格大约 12 年了。

虽然我喜欢使用下划线前缀表示 ivars,但我讨厌写作 @synthesize 由于所有重复而导致的行(这不是很 干燥)。我创建了一个宏来帮助完成此操作并减少代码重复。因此,代替:

@synthesize employee = _employee;

我这样写:

ddsynthesize(employee);

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

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

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

除了这里所说的之外,请务必阅读有关键值观察兼容命名的 Cocoa 文档。从长远来看,严格遵循这种模式将对你有很大帮助。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top