关于Memory Management的Apple文档:
您不应该使用访问器方法来设置实例变量的唯一地方是init方法和dealloc。要使用表示零的数字对象初始化计数器对象,可以按如下方式实现init方法:
要允许使用非零计数初始化计数器,您可以按如下方式实现initWithCount:方法:
- initWithCount:(NSNumber *)startingCount {
self = [super init];
if (self) {
count = [startingCount copy];
}
return self;
}
为什么不呢?
答案 0 :(得分:16)
请参阅我对this question的回答。
主要原因是因为子类可能会覆盖您的访问者并执行不同的操作。子类的访问器可能假定一个完全初始化的对象,即子类的init方法中的所有代码都已运行。事实上,当你的init方法运行时,它都没有。类似地,子类的访问器可能依赖于子类的dealloc方法没有运行。当你的dealloc方法运行时,这显然是错误的。
要扩展您的示例,如果您已完成
- initWithCount:(NSNumber *)startingCount {
self = [super init];
if (self) {
[self setCount: [startingCount copy]];
}
return self;
}
但是一个子类已经覆盖了setCount:除了设置你的count变量之外还做一些事情,你可能遇到麻烦。
答案 1 :(得分:2)
JeremyP提出了一个很好的观点。由于setter调用的语法总是涉及" self",其类型是在运行时确定的,因此子类实例可以调用其重写的setter版本,如果" self"是真正的子类对象......
但是,在某些情况下,您必须在初始化程序中使用setter。这是在超类中声明实例变量的时候;您无法直接访问实例变量,因此必须使用setter。
另一种情况是属性使用延迟初始化。在这种情况下,你必须通过吸气剂;如果不这样做,实例变量永远不会有机会被初始化。例如,EOCPerson类可能具有一个属性,可以访问代表每个人大脑的复杂对象。如果很少访问此属性并且设置成本很高,您可以在getter中懒惰地初始化它,如下所示:
- (EOCBrain*)brain { if (!_brain) {
_brain = [Brain new];
}
return _brain; }
如果你直接访问实例变量并且还没有调用getter,那么就不会设置大脑,你必须调用访问器才能访问大脑属性。
- Matt Galloway的EOC书籍Item7
答案 2 :(得分:1)
从OOP的角度来看(因为我没有使用objective-c的经验),你不会使用当前正在构造的对象的方法。这在某些语言中是可行的,但您已经可以访问私有变量。对象结构尚未完成,因此尚未准备好进行操作。一旦构造了对象,它就处于已知的良好状态(或者假定它是这样)并且它可以执行。
答案 3 :(得分:-3)
在现代目标C中,您应该能够在init中使用访问器方法。如果几乎不发生,编译器故障将很明显