Objective C 中的实例变量/方法参数命名
人们在命名实例变量和方法参数时遵循什么约定 - 特别是当方法参数用于设置 ivar(实例变量)时?
在 C++ 中,我经常使用 m_
前缀表示 ivars。 在 C# 中,我遵循纯粹使用 this.
来消除 ivars 歧义的惯例。 此后我也采用了 C++ 中的等效内容 (this->
)。
在 Objective C 中,我尝试了一些东西,但没有一个看起来真正令人满意。
除非有人提出了一些非常好的建议,否则我会接受这样的事实:我必须妥协(但是请不要让我使用 args 前缀!),所以我有兴趣听听大多数人的意见——尤其是那些已经使用 ObjC 一段时间的人的意见。
在发布本文之前,我做了一些尽职调查,并在以下位置找到了一些很好的资源:
他们给了我一些想法,但我仍然渴望听到其他人在做什么。
[编辑] 只是为了澄清:具体来说,我正在寻找如何区分 ivars 和方法参数 - 无论是通过前缀还是其他技术。
[编辑2] 感谢所有的回复和讨论点。 我不会结束这个,只是想说,正如我在对已接受答案的评论中指出的那样,我已经采用了在 init args 前面加上 the
前缀的约定(以及在 setter args 前面加上 < code>new,无论如何我都在这样做)。 这似乎是最好的力量平衡——即使我自己并不热衷于审美。
What conventions are people here following for naming of instance variables and method arguments - particularly when method arguments are used to set ivars (instance variables)?
In C++ I used to use the m_
prefix for ivars a lot. In C# I followed the convention of disambiguating purely by use of this.
for ivars. I've since adopted the equivalent in C++ too (this->
).
In Objective C I've tried a few things but none have really seemed satisfactory.
Unless someone suggests something really nice I am resigned to the fact that I'll have to compromise (but please, don't make me use the the
prefix for args!), so I'm interested to hear what the majority say - especially from those who have been using ObjC for a while.
I did some due diligence before posting this and a couple of good resources I found where:
- This style guide (briefly mentions my subject)
- This thread (a lot of ex C++ coders in there)
They give me some ideas, but I'm still keen to hear what others are doing.
[edit]
Just to clarify: It's specifically how you distinguish ivars from method args that I'm looking for - whether that's through prefixes or some other technique.
[edit 2]
Thanks for all the responses and discussion points. I'm not closing this, but will just say that, as I indicated in my comments to the accepted answer, I've gone with the convention of prefixing init args with the
(and setter args with new
, which I was doing anyway). This seems to be the best balance of forces - even if I'm not keen on the aesthetic myself.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
正如您所注意到的,如果参数名称与实例变量冲突,Cocoa 风格将使用像
theValue
这样的方法参数名称。 然而,在 Objective-C 2.0 风格的代码中,这种情况应该不会出现很多次。 假设您(通常)不应该直接访问实例变量。 这主要是因为这样做绕过了 Cocoa 中的键值观察机制。 相反,我们期望您通过 getter/setter 方法访问和改变属性。 在 Objective-C 2.0 中,很容易声明这些属性并自动@synthesize
getter/setter,因此没有太多理由不使用它们。 事实上,在 64 位系统上,运行时会自动为您创建实例变量,从而无需声明它们并减少使用它们的冲动。您应该直接访问实例变量的唯一时间是在
-init
和-dealloc
方法中:在这些情况下应直接使用 ivar 的原因是因为 getter/setter可能会产生依赖于完全初始化实例的副作用,从而使它们在对象状态完全初始化的
-init
和-dealloc
中变得危险。 在所有其他情况下,您应该使用self.ivar
(或[self ivar]
和[self setIvar:newValue]
)。似乎除
-initWithXX
之外的方法不应该存在命名冲突。 如果是的话,难道不应该将它们重构为不具有该参数或使类不具有实例变量吗?这样就只剩下
-initWithXX
方法,您经常会在其中发现参数和 ivar 之间发生冲突。 对于这种情况,如果您确实无法忍受 Cocoa 风格,则可以使用您提到的任何方法。 使用_
前缀有效并且相对常见(我相信@synthesize
的 setter 和 getter 在这种情况下会自动执行正确的操作,但您可能必须显式设置以_ivar
作为支持)。As you've noted, the Cocoa style is to use method argument names like
theValue
if the argument name will conflict with an instance variable. There shouldn't be many times that this comes up in Objective-C 2.0 style code, however. The assumption is that you shouldn't (usually) be accessing instance variables directly. Mostly this is because doing so circumvents the Key-Value Observing machinery in Cocoa. Rather, the expectation is that you'll access and mutate properties via getter/setter methods. In Objective-C 2.0, it's easy to declare these properties and automatically@synthesize
the getters/setters, so there's not much excuse for not using them. In fact, on 64-bit systems, the runtime will automatically create the instance variables for you, obviating the need to declare them and reducing the urge to use them.The only time you should be accessing instance variables directly is in
-init
and-dealloc
methods:The reason the ivar should be used directly in these cases is beacuse the getter/setter may have side effects that depend on a fully initialized instance, thus making them dangerous in
-init
and-dealloc
where the state of the object is fully initialized. In all other cases, you should be usingself.ivar
(or[self ivar]
and[self setIvar:newValue]
).It would seem that methods other than
-initWithXX
shouldn't have the naming conflict. If they do, shouldn't they be refactored to not have that parameter or for the Class to not have the instance variable?This leaves just the
-initWithXX
methods where you would often find a conflict between arguments and ivars. For this case, you can use any of the approaches you mention if you really can't stand the Cocoa style. Prefixing with_
works and is relatively common (I believe the@synthesize
'd setters and getters will automatically do the right thing in this case, but you may have to explicitly set the_ivar
as the backing).要完成所有已知的 Objective-C 样式指南,此处是 Google 版本。 他们所做的就是在成员变量名后面添加下划线。 例如
BOOL isActive_;
。因此,做出选择并坚持下去。 我也更喜欢我的应用程序使用“_”前缀。
To complete all known Objective-C styleguides here is the google version. What they do is to add an underscore after the the member varname. For instance
BOOL isActive_;
.So make a choice and stick with it. I also prefer the "_" prefix for my apps.
以下是 苹果做到了。
Here's how Apple does it.
Apple 生成的示例代码通常使用“_”前缀。 我想我还看到一些使用
mFoo
或m_foo
。 有些根本不关心前缀,只使用普通名称,但是稍后会变得混乱。 通常,在定义方法参数时,命名约定是使用“a”、“an”、“the”或“new”前缀。 例如:我发现这个约定非常有效。 我以前不关心前缀,但这有时会让事情变得混乱。 使用前缀清楚地表明它是一个实例变量。 Apple 在其 (iPhone) 示例代码中使用了
@synthesize bar = _bar
约定。无论如何,实例变量通常不会被使用,所以如果你发现“_”前缀烦人也没关系,因为你会使用
[self bar]
(或self.bar
如果你喜欢这类事情的话)无论如何。The sample code produced by Apple usually uses a "_" prefix. I think I also saw some using
mFoo
orm_foo
. Some don't bother with prefixes at all and just use a normal name, however that gets confusing later on. In general when defining method parameters, the naming convention is to use an "a", "an", "the" or "new" prefix. For instance:I find that this convention works quite well. I used to not bother with the prefix but that made things confusing sometimes. Using a prefix clearly indicates that it's an instance variable. The
@synthesize bar = _bar
convention is used by Apple in their (iPhone) sample code.The instance variable would not typically be used anyway, so if you find the "_" prefix annoying it doesn't matter, because you'd use
[self bar]
(orself.bar
if you're into that kind of thing) anyway.Obj-C 不像许多其他语言那样严格定义“风格”,这可能是一件好事,也可能是一件坏事,但这意味着大多数时候你需要自己找到一种好的编码风格。
您还可以通过 self. 访问 Obj-C 中的变量。 因此,如果您有实例变量 test,您可以通过 self->test 访问它,这是合法的并且始终有效。 但在大多数 Obj-C 程序员眼中它并不美丽。 它泄露了“秘密”,即对象实际上只是结构(更准确地说,对象引用是指向结构的指针),而实例变量实际上是结构成员。 这并不是说这真的是秘密,但 Obj-C 程序员似乎更喜欢在他们的代码中“隐藏”这一事实。
在名称中使用下划线“_”是一个非常糟糕的主意。 这里有人指出Apple为他们的代码保留了下划线,但实际上GCC已经为符号名称保留了下划线。 更准确地说,ANSI-C 标准已经规定,以两个下划线或一个下划线和一个大写字母开头的变量保留供编译器内部使用。 所以使用一个下划线理论上是有效的,但是一不小心名字以大写字母开头就失效了。
到目前为止,我尝试的是使用前缀 my、myName 代替 name,并使用前缀 self、selfName 代替 name; 乍一看有点奇怪,但在一大段代码中看起来并不算太糟糕。 至少立刻就让人觉得“与众不同”。 我也只是尝试了一个“i”,用 iName 代替 name(或 iname 代替 name),但我对这个解决方案不是很满意。
不过,我从来没有浪费时间考虑方法参数。 因为这并不重要。 这些变量与任何其他变量一样,除非它们被声明为常量。 它们甚至可以在方法内重新用于其他目的,因为它不会对调用者产生任何影响。 例如,
我认为该代码没有问题。 为什么我必须声明第二个堆栈变量,只要名称仍然有意义(如果我没有在 for 循环中按数字迭代图像,则名称当然没有意义,在这种情况下我会使用一个不同的变量 - 编译器实际上可能在堆栈上只为两者保留一个 int )。
Obj-C does not define "style" as strictly as many other languages, this might be a good thing or rather a bad one, but it means you are on your own to find a good coding style most of the time.
You can also access variables in Obj-C via self. So if you have an instance variable test, you can access it via self->test, this is legit and will always work. It's not beautiful in the eyes of most Obj-C programmers, though. It gives away the "secret", that objects are in fact just structs (more precisely, object refs are pointers to structs) and instance vars are in fact struct members. Not that this is really secret, but Obj-C programmers seems to prefer to "hide" this fact in their code.
Using underscore "_" in the name is a very bad idea. Someone here pointed out that Apple reserves underscore for their code, but actually GCC already reserves underscore for symbol names. More precisely, already the ANSI-C standard says that variables starting with either two underscores or one underscore and an upper case letter are reserved for the compiler's internal usage. So using one underscore is in theory valid, but accidentally start the name with an upper case letter and it becomes invalid.
What I tried so far was using the prefix my, myName instead of name, and using the prefix self, selfName instead of name; looks both somehow strange at first, but doesn't look too bad in a huge piece of code. At least immediately hits the eye as being "different". I also just tried a single "i", iName instead of name (or iname instead of name), but I was not very satisfied with that solution.
I never wasted time thinking about method parameters, though. Because it does not really matter. Those are variables like any other variables, unless they are declared constant. They can be even re-used for other purposes within the method, because it will have no affect on the caller. E.g.
I see no problem with that code. Why would I have to declare a second stack variable for that as long as the name still makes sense (if I'm not iterating over images by number in the for loop, the name makes no sense of course, in that case I would use a different variable for it - compiler may in fact reserve only one int on stack for both).