(目标C)做@synthesize myvar = _myvar(如果有的话)有什么好处?
可能重复:
如何在cocoaObjective-C类中的variables前面加下划线?
我不完全清楚(除了代码的可读性),为什么你要创build一个带有下划线前缀的内部variables,当你创build属性。
由于一切都是在内部处理的,为什么还要这样做呢,因为我们不向getter和setter添加任何代码?
即使我要添加一些代码到getter或setter,我不明白为什么我不能只检查myvar,而不是检查_myvar,然后将其分配给myvar。
任何人都可以给我一些解释,除了“这是因为这是每个人都做?” 我想了解这种做法背后的全部原因(这似乎是相当普遍的,即使没有自定义代码的getter和setter)。
谢谢!
一个Objective-C属性通常有一个支持实例variables(我猜你知道属性和实例variables之间的差异)。
该属性可能与实例variables名称不同。
例如,你可能有一个名为x
的实例variables,其属性名为y
。
您可以使用以下命令将y
属性合成到x
variables:
@synthesize y = x;
现在关于下划线。
当实例variables的方法参数与实例variables名称相同时,为实例variables使用下划线前缀,以防止命名冲突或编译器警告(阴影variables)是一种常见的做法。
下划线前缀也表明你指的是一个实例variables。
通过为实例variables使用下划线前缀,可以自由使用方法参数,堆栈variables等中不带下划线的名称。
但是在使用属性时,通常不希望用户编写下划线。
所以你通常有一个_x
实例variables的x
属性。
这就是为什么你写:
@synthesize x = _x;
举个例子:
@interface Test: NSObject { int x; } @property( readonly ) int x; @end
这是相当普遍的……但现在想象一下在执行:
- ( id )initWithX: ( int )x {}
我们有一个命名冲突。
在我们的方法中, x
将引用方法的参数。 而且没有很好的方式来访问x
实例variables。
根据您的编译器的警告标志,这也可能会产生一个警告( -Wshadow
)。
如果您为您的实例variables使用下划线前缀,则一切都很简单:
- ( id )initWithX: ( int )x { if( ( self = [ super init ] ) ) { _x = x; } return self; }
没有冲突,没有命名冲突,改进了阅读…只是一个很好的方法…
我自己也好奇这么多次 对其他人的回答感兴趣,但是我发现的一个原因是,当你使用getter / setter时,它会强迫你注意你是否直接访问伊娃。
self.myvar = @"blah";
和_myvar = @"blah";
VS
self.myvar = @"blah";
和myvar = @"blah";
离开self.
很容易self.
不小心把事故搞糟了,要把事故搞得更加困难。
当使用自己的财产时,很容易忘记“自我”:
[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_;
replace它@synthesize field = field_;
当我真的需要不同的伊娃时,比如它是自定义设置时间。