初始化属性,点表示法 [英] Initializing a property, dot notation
问题描述
在我的init方法中使用点表示法将保留属性初始化为nil是一个坏主意吗?
Is it a bad idea to use the dot notation to initialize retain properties to nil in my init methods?
具有任何普通属性,例如:
With any ordinary property like this:
@property (nonatomic, retain) id foo;
在我的初始化方法中说,我设置了self.foo = nil
.合成方法首先释放或自动释放foo
(不能完全确定潜在的影响).在第一次setter或getter调用之前,foo
是否保证为零?还是会指向随机垃圾,除非我显式设置foo = nil
而不使用点符号?
Say in my init method I set self.foo = nil
. The synthesized method first releases or autoreleases foo
(not exactly sure of the underlying impementation). Is foo
guaranted to be nil before the first setter or getter call? Or would it point to random garbage unless I explicitly set foo = nil
without the dot notation?
推荐答案
在我的init方法中使用点表示法将保留属性初始化为nil是一个坏主意吗?
Is it a bad idea to use the dot notation to initialize retain properties to nil in my init methods?
是的,这是个坏主意.
1)对象已按照alloc
+ init
序列清零,因此没有必要将其分配为nil.换句话说,除非您在访问器中有副作用(在此阶段也应避免访问器中的副作用),否则此调用是无用的.
1) The object has already been zeroed in the alloc
+init
sequence, so it is not necessary to assign it nil. In other words, this call is useless unless you have side effects in your accessors (side effects in accessors should also be avoided at this stage).
2)您不应该使用在部分构造状态(例如init
和dealloc
)中被覆盖的方法来 not 消息自身.
2) You should not message self with methods which are overridden while in partially constructed states (e.g. init
and dealloc
).
有第二个理由吗?我经常做self.array = [NSMutableArray array];在我的初始化方法中.
Is there a reason for #2? I often do self.array = [NSMutableArray array]; in my init methods.
原因是在部分构造状态(init...
,dealloc
,finalize
和许多copyWithZone:
实现)期间,您的对象不应对类接口的行为感兴趣.您的班级 应该对正确初始化(如init...
)和清除自身及其成员(如dealloc
) 感兴趣,而不会引起副作用.
The reason is that your object should not be interested in the class interface's behavior during partially constructed states (init...
, dealloc
, finalize
, and many copyWithZone:
implementations). your class should be interested in initializing properly (as in init...
) and cleaning up after itself including its members (as in dealloc
) without introducing side-effects.
考虑以下示例,您可以将其构建为OS X的基础工具:
consider this example, which you can build as a Foundation tool for OS X:
#import <Foundation/Foundation.h>
enum { UseItTheRightWay = true -OR- false };
@interface MONObjectA : NSObject
{
NSMutableArray * array;
}
@property (nonatomic, retain) NSArray * array;
@end
@implementation MONObjectA
@synthesize array;
- (id)init
{
self = [super init];
if (0 != self) {
NSLog(@"%s, %@",__PRETTY_FUNCTION__, self);
if (UseItTheRightWay) {
array = [NSMutableArray new];
}
else {
self.array = [NSMutableArray array];
}
}
return self;
}
- (void)dealloc
{
NSLog(@"%s, %@",__PRETTY_FUNCTION__, self);
if (UseItTheRightWay) {
[array release], array = nil;
}
else {
self.array = nil;
}
[super dealloc];
}
@end
@interface MONObjectB : MONObjectA
{
NSMutableSet * set;
}
@end
@implementation MONObjectB
- (id)init
{
self = [super init];
if (0 != self) {
NSLog(@"%s, %@",__PRETTY_FUNCTION__, self);
set = [NSMutableSet new];
}
return self;
}
- (void)dealloc
{
NSLog(@"%s, %@",__PRETTY_FUNCTION__, self);
[set release], set = nil;
[super dealloc];
}
- (void)setArray:(NSArray *)arg
{
NSLog(@"%s, %@",__PRETTY_FUNCTION__, self);
NSMutableSet * tmp = arg ? [[NSMutableSet alloc] initWithArray:arg] : nil;
[super setArray:arg];
[set release];
set = tmp;
}
@end
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
[[MONObjectB new] release];
/* the tool must be named 'Props' for this to work as expected, or you can just change 'Props' to the executable's name */
system("leaks Props");
[pool drain];
return 0;
}
此测试中用于切换行为的主开关是UseItTheRightWay
.
The main switch to toggle behavior in this test is UseItTheRightWay
.
如果UseItTheRightWay
为 true ,我们将得到结果:
If UseItTheRightWay
is true, we are given the result:
2011-05-09 01:52:11.175 Props[45138:a0f] -[MONObjectA init], <MONObjectB: 0x10010c750>
2011-05-09 01:52:11.177 Props[45138:a0f] -[MONObjectB init], <MONObjectB: 0x10010c750>
2011-05-09 01:52:11.179 Props[45138:a0f] -[MONObjectB dealloc], <MONObjectB: 0x10010c750>
2011-05-09 01:52:11.179 Props[45138:a0f] -[MONObjectA dealloc], <MONObjectB: 0x10010c750>
leaks Report Version: 2.0
Process: Props [45138]
< --- snip --- >
Process 45138: 1581 nodes malloced for 296 KB
Process 45138: 0 leaks for 0 total leaked bytes.
如果UseItTheRightWay
是 false ,我们得到的结果是:
And if UseItTheRightWay
is false, we are given the result:
2011-05-09 01:55:51.611 Props[45206:a0f] -[MONObjectA init], <MONObjectB: 0x10010c750>
2011-05-09 01:55:51.614 Props[45206:a0f] -[MONObjectB setArray:], <MONObjectB: 0x10010c750>
2011-05-09 01:55:51.615 Props[45206:a0f] -[MONObjectB init], <MONObjectB: 0x10010c750>
2011-05-09 01:55:51.617 Props[45206:a0f] -[MONObjectB dealloc], <MONObjectB: 0x10010c750>
2011-05-09 01:55:51.618 Props[45206:a0f] -[MONObjectA dealloc], <MONObjectB: 0x10010c750>
2011-05-09 01:55:51.618 Props[45206:a0f] -[MONObjectB setArray:], <MONObjectB: 0x10010c750>
leaks Report Version: 2.0
Process: Props [45206]
< --- snip --- >
Process 45206: 1585 nodes malloced for 297 KB
Process 45206: 1 leak for 48 total leaked bytes.
Leak: 0x100110970 size=48 zone: DefaultMallocZone_0x100005000 instance of 'NSCFSet', type ObjC, implemented in Foundation
0x70294ff8 0x00007fff 0x00001080 0x00000001 .O)p............
0x00000001 0x00000000 0x00000000 0x00010000 ................
0x707612a8 0x00007fff 0x00000000 0x00000000 ..vp............
问题1
此示例的明显失败是在dealloc
中引入的泄漏.
This example's obvious failure is the leak, introduced in dealloc
.
问题2
咬你的第二件事是微妙的:
The second thing that will bite you is subtler:
-[MONObjectA init]
-[MONObjectB setArray:]
-[MONObjectB init]
这是什么??? -[MONObjectB setArray:]
被称为 before -[MONObjectB init]
?这意味着MONObjectB
的实现是在 -[MONObjectB init]
之前甚至在-[MONObjectA init]
退出之前使用的.那不好= \
What's this??? -[MONObjectB setArray:]
is called before -[MONObjectB init]
? That means that MONObjectB
's implementation is used before -[MONObjectB init]
, and even before -[MONObjectA init]
has exited. That's no good =\
非创新性设计只会产生许多不良的副作用,怪异的行为,泄漏等等.复杂的设计将以非常明显的,非常微妙的方式失败,这可能很难追踪.最好避免因这种琐碎的书面差异而导致维护麻烦,并从一开始就以正确的方式编写类(即使您可以在相当长的一段时间内避免这样做,而没有明显的副作用).
Nontrivial designs will just produce a bunch of undesirable side effects, weird behavior, leaks, and so on. Complex designs will fail in very obvious, and very subtle ways which can be very difficult to track down. it's best to avoid maintenance headaches over such trivial written differences, and to write classes the proper way from the start (even though you could get away doing this for quite some time, without obvious side effects).
这篇关于初始化属性,点表示法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!