2011-11-16 38 views
8

可能重复:
How does an underscore in front of a variable in a cocoa objective-c class work?(Objective C)做@synthesize myvar = _myvar(如果有的话)有什么好处?

这是不完全清楚,我,为什么你想你的时候用下划线前缀创建一个内部变量(比代码的可读性等)创建该属性。

因为一切都在内部处理,为什么还要这样做,因为我们不向getter和setter添加任何代码?

即使我需要向getter或setter添加一些代码,我也不明白为什么我不能仅仅检查myvar,而不是检查_myvar然后将其分配给myvar。

任何人都可以给我一些解释,除了“这是因为这是每个人都做的吗?”我想了解这种做法背后的全部原因(即使没有getter和setter的自定义代码,这似乎也很常见)。

谢谢!

+1

有很多很多这个问题的重复:[1](http://stackoverflow.com/questions/3521254/)[2](http://stackoverflow.com/questions/822487/)[3](http://stackoverflow.com/questions/2371489)[4](http://stackoverflow.com/questions/5582448/)[5](http://stackoverflow.com/questions/837559/)[6](http://stackoverflow.com/questions/6064283 /)[和更多...](http://stackoverflow.com/search?q=objc+property+underscore) –

回答

8

Objective-C属性通常有一个后台实例变量(我猜你知道属性和实例变量之间的区别)。

该属性可能与实例变量名称不同。

例如,您可能有一个名为x的实例变量,其名称为y

您可以将y财产综合使用x变量:

@synthesize y = x; 

现在谈谈下划线。

当实例变量的方法参数与实例变量名称相同时,为实例变量使用下划线前缀以防止命名冲突或编译器警告(阴影变量)是一种常见做法。

下划线前缀还表明您指的是实例变量。

通过使用实例变量下划线前缀,你可以自由地使用该名称没有方法的参数下划线,堆栈变量等

但在使用物业时,你通常不希望用户写下划线。

所以你通常有x属性为_x实例变量。

这就是为什么你写的:

@synthesize x = _x; 

让我们举个例子:

@interface Test: NSObject 
{ 
    int x; 
} 

@property(readonly) int x; 

@end 

这是很常见的...但现在想象一下在执行:

- (id)initWithX: (int)x 
{} 

我们有一个命名冲突。

在我们的方法中,x将引用该方法的参数。而且没有办法访问x实例变量。

根据编译器的警告标志,这也可能会生成警告(-Wshadow)。

如果您使用您的实例变量下划线前缀,一切都只是简单:

- (id)initWithX: (int)x 
{ 
    if((self = [ super init ])) 
    { 
     _x = x; 
    } 

    return self; 
} 

没有冲突,没有命名冲突,提高阅读...只是一个很好的方式...

+0

真棒,谢谢!!!!!这是我寻找的原因,在很多情况下确实是至关重要的。 – user1006198

+0

不客气! :)另请注意,Apple禁止在ObjC编码指南中使用下划线前缀。它不适用于实例变量。 – Macmade

+0

我不认为来自C/C++/Java或其他语言背景的人知道属性和实例变量之间的差异。是的,我们都知道实例变量是什么,但**属性**这个词似乎并不熟悉,除了OC家伙:)。 –

9

我自己想过很多次。对其他人的回答感兴趣,但我发现的一个原因是它迫使你注意,如果你应该使用getter/setter时直接访问伊娃。

self.myvar = @"blah";_myvar = @"blah";

VS

self.myvar = @"blah";myvar = @"blah";

这很容易因意外离开self.出来......这是一个困难得多意外把_英寸

+0

非常好,把肯尼;我没有考虑到你有getter和setter的原因是为了避免直接访问ivar :) – user1006198

1

当使用自我的特性,很容易忘记“自我”:

[self.field doSomething]; // what you probably want 
[self setField:someObject]; // also kosher 
self.field = someObject; // ditto, although not my style 

[field doSomething] // might work.. but will bite you eventually 
field = someObject; // almost certainly wrong anywhere outside a custom setter 

如果属性和伊娃具有完全相同的名称,后者的情况下将编译没有抱怨,似乎工作...直到他们没有,并且你得到一个奇怪的难以重现的边缘案例错误。

如果伊娃有一个稍微不同的名称,比如附带尾随_,编译器会阻止你并让你明确地决定:我想直接引用这里的属性还是伊娃?

(所有这一切说,我很懒惰,经常做@synthesize field;,后来与@synthesize field = field_;取代它,当我真正需要不同的伊娃,说时,它的自定义的制定者写作时间。)

+0

感谢您的回复! – user1006198