Being new to Objective-C (but a long term C/++) programmer I'm looking for advice/recommendations on naming conventions for variables.
作为Objective-C(但是长期的C / ++)程序员的新手,我正在寻找有关变量命名约定的建议/建议。
My personal preference would be to utilize a prefix for instance variables both for clarity within functions and to prevent shadowing of function parameters. However I'm a fan of properties which rules out prefixes (unless you also prefix your property names, which doesn't work too well and looks daft). Similarly I could use the "self.variable" convention, but only if I make EVERYTHING a property.
我个人的偏好是利用前缀作为实例变量,既为了功能内的清晰度,又为了防止功能参数的阴影。然而,我是排除前缀的属性的粉丝(除非你也为你的属性名称添加前缀,这不是很好,看起来很愚蠢)。同样地,我可以使用“self.variable”约定,但前提是我将一切都设为属性。
So given the code below what's your preferred naming style for instance/function variables? And if you don't bother, how do you deal with shadowing on function params?
所以给定下面的代码你的首选实例/函数变量的命名风格是什么?如果你不打扰,你如何处理函数参数的阴影?
@interface GridItem : NSObject
{
CGRect _rect;
...
}
@end
-(void) initFromRect:(CGRect)rect
{
_rect = rect;
...
}
Cheers!
10 个解决方案
#1
15
Most Cocoa projects use underbar as a non-IBOutlet
instance variable prefix, and use no prefix for IBOutlet
instance variables.
大多数Cocoa项目使用underbar作为非IBOutlet实例变量前缀,并且对IBOutlet实例变量不使用前缀。
The reason I don't use underbars for IBOutlet
instance variables is that when a nib file is loaded, if you have a setter method for a connected outlet, that setter will be called. However this mechanism does not use Key-Value Coding, so an IBOutlet whose name is prefixed with an underbar (e.g. _myField
) will not be set unless the setter is named exactly like the outlet (e.g. set_myField:
), which is non-standard and gross.
我没有为IBOutlet实例变量使用下划线的原因是,当加载nib文件时,如果你有一个连接插座的setter方法,那么将调用该setter。然而,这种机制不使用键值编码,因此不会设置名称以下划线为前缀的IBOutlet(例如_myField),除非setter的名称与插座完全相同(例如set_myField :),这是非标准的毛。
Also, be aware that using properties like self.myProp
is not the same as accessing instance variables. You are sending a message when you use a property, just like if you used bracket notation like [self myProp]
. All properties do is give you a concise syntax for specifying both the getter and setter in a single line, and allow you to synthesize their implementation; they do not actually short-circuit the message dispatch mechanism. If you want to access an instance variable directly but prefix it with self
you need to treat self
as a pointer, like self->myProp
which really is a C-style field access.
另外,请注意使用self.myProp等属性与访问实例变量不同。您在使用属性时发送消息,就像使用[self myProp]之类的括号表示法一样。所有属性都为您提供了一个简洁的语法,用于在一行中指定getter和setter,并允许您合成它们的实现;它们实际上并没有使消息调度机制短路。如果你想直接访问一个实例变量但是用self作为前缀,你需要将self视为一个指针,比如self-> myProp,它实际上是一个C风格的字段访问。
Finally, never use Hungarian notation when writing Cocoa code, and shy away from other prefixes like "f" and "m_" — that will mark the code as having been written by someone who doesn't "get it" and will cause it to be viewed by suspicion by other Cocoa developers.
最后,在编写Cocoa代码时永远不要使用匈牙利符号,并回避其他前缀如“f”和“m_” - 这会将代码标记为由没有“得到它”的人编写并将导致它被其他Cocoa开发者怀疑。
In general, follow the advice in the Coding Guidelines for Cocoa document at the Apple Developer Connection, and other developers will be able to pick up and understand your code, and your code will work well with all of the Cocoa features that use runtime introspection.
通常,请遵循Apple Developer Connection中的Cocoa编码指南文档中的建议,其他开发人员将能够学习和理解您的代码,并且您的代码将适用于使用运行时内省的所有Cocoa功能。
Here's what a window controller class might look like, using my conventions:
以下是使用我的约定的窗口控制器类的外观:
// 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
You'll see that I'm using the instance variable that references an Employee
directly in my -init
and -dealloc
method, while I'm using the property in other methods. That's generally a good pattern with properties: Only ever touch the underlying instance variable for a property in initializers, in -dealloc
, and in the getter and setter for the property.
您将看到我正在使用直接在我的-init和-dealloc方法中引用Employee的实例变量,而我在其他方法中使用该属性。这通常是一个带有属性的好模式:只触及初始值设定项中的属性的底层实例变量,-dealloc以及属性的getter和setter。
#2
8
I follow Chris Hanson's advice in regards to the underscore ivar prefix, though I admit I do use underscore's for IBOutlets as well. However, I've recently starting moving my IBOutlet
declarations to the @property
line, as per @mmalc's suggestion. The benefit is that all my ivars now have an underscore and standard KVC setters are called (i.e. setNameField:
). Also, the outlet names don't have underscores in Interface Builder.
我遵循Chris Hanson关于下划线ivar前缀的建议,但我承认我也使用下划线来表示IBOutlets。但是,根据@ mmalc的建议,我最近开始将我的IBOutlet声明移到@property行。好处是我的所有ivars现在都有一个下划线,并且调用标准的KVC setter(即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
#3
3
You can use the underbar prefix on your ivars and still use the non-underbar name for your properties. For synthesized accessors, just do this:
您可以在ivars上使用下划线前缀,并仍然使用属性的非下划线名称。对于合成访问器,只需执行以下操作:
@synthesize foo = _foo;
This tells the compiler to synthesize the foo property using the_foo ivar.
这告诉编译器使用the_foo ivar合成foo属性。
If you write your own accessors, then you just use the underbar ivar in your implementation and keep the non-underbar method name.
如果您编写自己的访问器,那么您只需在实现中使用underbar ivar并保留非underbar方法名称。
#4
2
Personally, I follow the Cocoa naming conventions, using camel-casing for functions and variables, and capitalized camel-casing for object names (without the leading NS of course).
就个人而言,我遵循Cocoa命名约定,使用camel-casing作为函数和变量,并使用camel-casing作为对象名称(当然没有前导NS)。
I find type prefixing makes code more opaque to anyone who didn't write it (since everyone invariably uses different prefixes), and in a modern IDE it's not really that difficult to figure out something's type.
我发现类型前缀使得代码对于没有编写代码的人来说更加不透明(因为每个人总是使用不同的前缀),而在现代IDE中,找出某些类型并不是那么困难。
#5
2
With the introduction of properties I see no need for prefixing "_" to class instance variables. You can set a simple rule (described in your header file) that any variables to be accessed external to the class must be accessed via the property, or by using custom methods on the class to affect values. This to me seems much cleaner than having names with "_" stuck on the front of them. It also properly encapsulates the values so that you can control how they are changed.
随着属性的引入,我认为不需要为类实例变量添加前缀“_”。您可以设置一个简单的规则(在头文件中描述),必须通过属性访问要在类外部访问的任何变量,或者使用类上的自定义方法来影响值。这对我来说似乎比在他们的前面贴着“_”的名字要清晰得多。它还可以正确封装值,以便您可以控制它们的更改方式。
#6
1
I don't like using underscores as prefixes for any identifiers, because C and C++ both reserve certain underscore prefixes for use by the implementation.
我不喜欢使用下划线作为任何标识符的前缀,因为C和C ++都保留了某些下划线前缀供实现使用。
I think using "self.variable" is ugly.
我认为使用“self.variable”是丑陋的。
In general, I use unadorned identifiers (that is, no prefixes nor suffixes) for instance variables. If your class is so complicated that you can't remember the instance variables, you're in trouble. So for your example, I'd use "rect" as the name of the instance variable and "newRect" or "aRect" as the parameter name.
通常,我使用简单的标识符(即没有前缀或后缀)作为实例变量。如果你的课程如此复杂以至于你无法记住实例变量,那你就麻烦了。因此,对于您的示例,我将使用“rect”作为实例变量的名称,并使用“newRect”或“aRect”作为参数名称。
#7
1
Andrew: There actually are plenty of Cocoa developers who don't use instance variable prefixes at all. It's also extremely common in the Smalltalk world (in fact, I'd say it's nearly unheard-of in Smalltalk to use prefixes on instance variables).
Andrew:实际上有很多Cocoa开发人员根本不使用实例变量前缀。它在Smalltalk世界中也非常普遍(事实上,我认为在Smalltalk中几乎闻所未闻的是在实例变量上使用前缀)。
Prefixes on instance variables have always struck me as a C++-ism that was brought over to Java and then to C#. Since the Objective-C world was largely parallel to the C++ world, where as the Java and C# worlds are successors to it, that would explain the "cultural" difference you might see on this between the different sets of developers.
实例变量的前缀总是让我感到震惊,因为C ++ - 主义被带到Java然后被带到C#。由于Objective-C世界在很大程度上与C ++世界平行,因为Java和C#世界是它的继承者,这可以解释您在不同的开发人员之间可能会看到的“文化”差异。
#8
1
My style is hybrid and really a holdover from PowerPlant days:
我的风格是混合动力,真的是PowerPlant时代的延续:
THe most useful prefixes I use are "in" and "out" for function/method parameters. This helps you know what the parameters are for at a glance and really helps prevent conflicts between method parameters and instance variables (how many times have you seen the parameter "table" conflict with an instance variable of the same name). E.g.:
我使用的最有用的前缀是函数/方法参数的“in”和“out”。这有助于您一目了然地了解参数,并确实有助于防止方法参数和实例变量之间的冲突(您看到参数“table”与同名实例变量冲突的次数)。例如。:
- (void)doSomethingWith:(id)inSomeObject error:(NSError **)outError;
Then I use the bare name for instance variables and property names:
然后我使用裸名称作为实例变量和属性名称:
Then I use "the" as a prefix for local variables: theTable, theURL, etc. Again this helps differentiate between local and and instance variables.
然后我使用“the”作为局部变量的前缀:theTable,theURL等。这有助于区分本地变量和实例变量。
Then following PowerPlant styling I use a handful of other prefixes: k for constants, E for enums, g for globals, and s for statics.
然后按照PowerPlant样式我使用了一些其他前缀:k代表常量,E代表枚举,g代表全局,s代表静态。
I've been using this style for something like 12 years now.
我已经用这种风格做了12年了。
#9
1
While I love using the underscore prefix for ivars, I loathe writing @synthesize
lines because of all the duplication (it's not very DRY). I created a macro to help do this and reduce code duplication. Thus, instead of:
虽然我喜欢使用下划线前缀用于ivars,但我不喜欢编写@synthesize行,因为所有重复(它不是很干)。我创建了一个宏来帮助实现这一点并减少代码重复。因此,而不是:
@synthesize employee = _employee;
I write this:
我写这个:
ddsynthesize(employee);
It's a simple macro using token pasting to add an underscore to the right hand side:
这是一个使用令牌粘贴的简单宏来向右侧添加下划线:
#define ddsynthesize(_X_) @synthesize _X_ = _##_X_
The only downside is that it will confuse Xcode's refactoring tool, and it won't get renamed, if you rename the property by refactoring.
唯一的缺点是它会混淆Xcode的重构工具,如果你通过重构重命名属性,它将不会被重命名。
#10
1
Along with what's been said here, be sure to read the Cocoa documentation on Key Value Observing compliant naming. Strictly following this pattern will help you greatly in the long run.
除了这里所说的内容之外,请务必阅读关于Key Value Observing兼容命名的Cocoa文档。从长远来看,严格遵循这种模式将对您有很大帮助。
#1
15
Most Cocoa projects use underbar as a non-IBOutlet
instance variable prefix, and use no prefix for IBOutlet
instance variables.
大多数Cocoa项目使用underbar作为非IBOutlet实例变量前缀,并且对IBOutlet实例变量不使用前缀。
The reason I don't use underbars for IBOutlet
instance variables is that when a nib file is loaded, if you have a setter method for a connected outlet, that setter will be called. However this mechanism does not use Key-Value Coding, so an IBOutlet whose name is prefixed with an underbar (e.g. _myField
) will not be set unless the setter is named exactly like the outlet (e.g. set_myField:
), which is non-standard and gross.
我没有为IBOutlet实例变量使用下划线的原因是,当加载nib文件时,如果你有一个连接插座的setter方法,那么将调用该setter。然而,这种机制不使用键值编码,因此不会设置名称以下划线为前缀的IBOutlet(例如_myField),除非setter的名称与插座完全相同(例如set_myField :),这是非标准的毛。
Also, be aware that using properties like self.myProp
is not the same as accessing instance variables. You are sending a message when you use a property, just like if you used bracket notation like [self myProp]
. All properties do is give you a concise syntax for specifying both the getter and setter in a single line, and allow you to synthesize their implementation; they do not actually short-circuit the message dispatch mechanism. If you want to access an instance variable directly but prefix it with self
you need to treat self
as a pointer, like self->myProp
which really is a C-style field access.
另外,请注意使用self.myProp等属性与访问实例变量不同。您在使用属性时发送消息,就像使用[self myProp]之类的括号表示法一样。所有属性都为您提供了一个简洁的语法,用于在一行中指定getter和setter,并允许您合成它们的实现;它们实际上并没有使消息调度机制短路。如果你想直接访问一个实例变量但是用self作为前缀,你需要将self视为一个指针,比如self-> myProp,它实际上是一个C风格的字段访问。
Finally, never use Hungarian notation when writing Cocoa code, and shy away from other prefixes like "f" and "m_" — that will mark the code as having been written by someone who doesn't "get it" and will cause it to be viewed by suspicion by other Cocoa developers.
最后,在编写Cocoa代码时永远不要使用匈牙利符号,并回避其他前缀如“f”和“m_” - 这会将代码标记为由没有“得到它”的人编写并将导致它被其他Cocoa开发者怀疑。
In general, follow the advice in the Coding Guidelines for Cocoa document at the Apple Developer Connection, and other developers will be able to pick up and understand your code, and your code will work well with all of the Cocoa features that use runtime introspection.
通常,请遵循Apple Developer Connection中的Cocoa编码指南文档中的建议,其他开发人员将能够学习和理解您的代码,并且您的代码将适用于使用运行时内省的所有Cocoa功能。
Here's what a window controller class might look like, using my conventions:
以下是使用我的约定的窗口控制器类的外观:
// 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
You'll see that I'm using the instance variable that references an Employee
directly in my -init
and -dealloc
method, while I'm using the property in other methods. That's generally a good pattern with properties: Only ever touch the underlying instance variable for a property in initializers, in -dealloc
, and in the getter and setter for the property.
您将看到我正在使用直接在我的-init和-dealloc方法中引用Employee的实例变量,而我在其他方法中使用该属性。这通常是一个带有属性的好模式:只触及初始值设定项中的属性的底层实例变量,-dealloc以及属性的getter和setter。
#2
8
I follow Chris Hanson's advice in regards to the underscore ivar prefix, though I admit I do use underscore's for IBOutlets as well. However, I've recently starting moving my IBOutlet
declarations to the @property
line, as per @mmalc's suggestion. The benefit is that all my ivars now have an underscore and standard KVC setters are called (i.e. setNameField:
). Also, the outlet names don't have underscores in Interface Builder.
我遵循Chris Hanson关于下划线ivar前缀的建议,但我承认我也使用下划线来表示IBOutlets。但是,根据@ mmalc的建议,我最近开始将我的IBOutlet声明移到@property行。好处是我的所有ivars现在都有一个下划线,并且调用标准的KVC setter(即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
#3
3
You can use the underbar prefix on your ivars and still use the non-underbar name for your properties. For synthesized accessors, just do this:
您可以在ivars上使用下划线前缀,并仍然使用属性的非下划线名称。对于合成访问器,只需执行以下操作:
@synthesize foo = _foo;
This tells the compiler to synthesize the foo property using the_foo ivar.
这告诉编译器使用the_foo ivar合成foo属性。
If you write your own accessors, then you just use the underbar ivar in your implementation and keep the non-underbar method name.
如果您编写自己的访问器,那么您只需在实现中使用underbar ivar并保留非underbar方法名称。
#4
2
Personally, I follow the Cocoa naming conventions, using camel-casing for functions and variables, and capitalized camel-casing for object names (without the leading NS of course).
就个人而言,我遵循Cocoa命名约定,使用camel-casing作为函数和变量,并使用camel-casing作为对象名称(当然没有前导NS)。
I find type prefixing makes code more opaque to anyone who didn't write it (since everyone invariably uses different prefixes), and in a modern IDE it's not really that difficult to figure out something's type.
我发现类型前缀使得代码对于没有编写代码的人来说更加不透明(因为每个人总是使用不同的前缀),而在现代IDE中,找出某些类型并不是那么困难。
#5
2
With the introduction of properties I see no need for prefixing "_" to class instance variables. You can set a simple rule (described in your header file) that any variables to be accessed external to the class must be accessed via the property, or by using custom methods on the class to affect values. This to me seems much cleaner than having names with "_" stuck on the front of them. It also properly encapsulates the values so that you can control how they are changed.
随着属性的引入,我认为不需要为类实例变量添加前缀“_”。您可以设置一个简单的规则(在头文件中描述),必须通过属性访问要在类外部访问的任何变量,或者使用类上的自定义方法来影响值。这对我来说似乎比在他们的前面贴着“_”的名字要清晰得多。它还可以正确封装值,以便您可以控制它们的更改方式。
#6
1
I don't like using underscores as prefixes for any identifiers, because C and C++ both reserve certain underscore prefixes for use by the implementation.
我不喜欢使用下划线作为任何标识符的前缀,因为C和C ++都保留了某些下划线前缀供实现使用。
I think using "self.variable" is ugly.
我认为使用“self.variable”是丑陋的。
In general, I use unadorned identifiers (that is, no prefixes nor suffixes) for instance variables. If your class is so complicated that you can't remember the instance variables, you're in trouble. So for your example, I'd use "rect" as the name of the instance variable and "newRect" or "aRect" as the parameter name.
通常,我使用简单的标识符(即没有前缀或后缀)作为实例变量。如果你的课程如此复杂以至于你无法记住实例变量,那你就麻烦了。因此,对于您的示例,我将使用“rect”作为实例变量的名称,并使用“newRect”或“aRect”作为参数名称。
#7
1
Andrew: There actually are plenty of Cocoa developers who don't use instance variable prefixes at all. It's also extremely common in the Smalltalk world (in fact, I'd say it's nearly unheard-of in Smalltalk to use prefixes on instance variables).
Andrew:实际上有很多Cocoa开发人员根本不使用实例变量前缀。它在Smalltalk世界中也非常普遍(事实上,我认为在Smalltalk中几乎闻所未闻的是在实例变量上使用前缀)。
Prefixes on instance variables have always struck me as a C++-ism that was brought over to Java and then to C#. Since the Objective-C world was largely parallel to the C++ world, where as the Java and C# worlds are successors to it, that would explain the "cultural" difference you might see on this between the different sets of developers.
实例变量的前缀总是让我感到震惊,因为C ++ - 主义被带到Java然后被带到C#。由于Objective-C世界在很大程度上与C ++世界平行,因为Java和C#世界是它的继承者,这可以解释您在不同的开发人员之间可能会看到的“文化”差异。
#8
1
My style is hybrid and really a holdover from PowerPlant days:
我的风格是混合动力,真的是PowerPlant时代的延续:
THe most useful prefixes I use are "in" and "out" for function/method parameters. This helps you know what the parameters are for at a glance and really helps prevent conflicts between method parameters and instance variables (how many times have you seen the parameter "table" conflict with an instance variable of the same name). E.g.:
我使用的最有用的前缀是函数/方法参数的“in”和“out”。这有助于您一目了然地了解参数,并确实有助于防止方法参数和实例变量之间的冲突(您看到参数“table”与同名实例变量冲突的次数)。例如。:
- (void)doSomethingWith:(id)inSomeObject error:(NSError **)outError;
Then I use the bare name for instance variables and property names:
然后我使用裸名称作为实例变量和属性名称:
Then I use "the" as a prefix for local variables: theTable, theURL, etc. Again this helps differentiate between local and and instance variables.
然后我使用“the”作为局部变量的前缀:theTable,theURL等。这有助于区分本地变量和实例变量。
Then following PowerPlant styling I use a handful of other prefixes: k for constants, E for enums, g for globals, and s for statics.
然后按照PowerPlant样式我使用了一些其他前缀:k代表常量,E代表枚举,g代表全局,s代表静态。
I've been using this style for something like 12 years now.
我已经用这种风格做了12年了。
#9
1
While I love using the underscore prefix for ivars, I loathe writing @synthesize
lines because of all the duplication (it's not very DRY). I created a macro to help do this and reduce code duplication. Thus, instead of:
虽然我喜欢使用下划线前缀用于ivars,但我不喜欢编写@synthesize行,因为所有重复(它不是很干)。我创建了一个宏来帮助实现这一点并减少代码重复。因此,而不是:
@synthesize employee = _employee;
I write this:
我写这个:
ddsynthesize(employee);
It's a simple macro using token pasting to add an underscore to the right hand side:
这是一个使用令牌粘贴的简单宏来向右侧添加下划线:
#define ddsynthesize(_X_) @synthesize _X_ = _##_X_
The only downside is that it will confuse Xcode's refactoring tool, and it won't get renamed, if you rename the property by refactoring.
唯一的缺点是它会混淆Xcode的重构工具,如果你通过重构重命名属性,它将不会被重命名。
#10
1
Along with what's been said here, be sure to read the Cocoa documentation on Key Value Observing compliant naming. Strictly following this pattern will help you greatly in the long run.
除了这里所说的内容之外,请务必阅读关于Key Value Observing兼容命名的Cocoa文档。从长远来看,严格遵循这种模式将对您有很大帮助。