Objective c 如何重置某些对象';属性的初始值?

Objective c 如何重置某些对象';属性的初始值?,objective-c,Objective C,假设我有一个“dog”类的对象“dog”,其属性可以分为两组: (A) 分配dog时,只能初始化一次的属性 (B) 必须每隔一段时间重新初始化(重置)一次的属性 所以我需要一个方法“resetB”,它使用self重置组(B)中的属性,即 -(void) resetB { self.propB1 = initValB1; self.propB2 = initValB2; self.propB3 = initValB3; } 为了避免重复代码(实际情况要复杂得多,有几十个属

假设我有一个“dog”类的对象“dog”,其属性可以分为两组:

(A) 分配dog时,只能初始化一次的属性
(B) 必须每隔一段时间重新初始化(重置)一次的属性

所以我需要一个方法“resetB”,它使用self重置组(B)中的属性,即

-(void) resetB {
    self.propB1 = initValB1;
    self.propB2 = initValB2;
    self.propB3 = initValB3;
}
为了避免重复代码(实际情况要复杂得多,有几十个属性),我想从我的“init”调用“resetB”,使init wuld看起来像这样

-(id) init {
    self = [super init];
    if ( self ) {
        propA1 = initValA1;
        propA2 = initValA2;
        propA3 = initValA3;
        [self resetB];
    }
    return self;
}
好的,但现在我担心我正在通过我的“init”方法传递“self”,人们说这是被考虑的。。。“不礼貌”。。。(可以这么说)。

我的问题是:我是否过于担心礼仪问题,而实际上按照上述方式做是安全的?或者,也许,重复代码(必须保持同步)是较小的罪恶?或者还有另一种“正确”的方法吗?

我认为从
init
内部调用
self
上的方法被认为是潜在危险的唯一原因是当您调用属性设置器或KVO可能导致副作用的另一种方法时

如果您知道该方法不会引起副作用,那么调用它是安全的,并且从多个版本的
init
awakeFromNib
等调用一个常见的“设置方法”是非常正常的

EDIT正如@sergio所提到的,避免从
init
self
调用方法的另一个原因是它可能被未正确初始化的子类覆盖。解决这个问题的一种方法是将重置实现放在一个私有方法中,该方法从
init
调用,并让公共方法也使用私有方法。虽然私有方法也可以被覆盖,但显然它不应该被覆盖:

@interface MyClass ()
- (void)_resetB;
@end

@implementation MyClass

-(id) init {
    self = [super init];
    if ( self ) {
        _propA1 = initValA1;
        _propA2 = initValA2;
        _propA3 = initValA3;
        [self _resetB];
    }
    return self;
}

- (void)resetB
{
    [self _resetB];
}

#pragma mark - Private Methods

- (void)_resetB
{
    _propB1 = initValB1;
    _propB2 = initValB2;
    _propB3 = initValB3;
}

@end

当满足以下两个条件时,从
init
self
发送消息是安全的:

  • 您正在调用的方法不会被派生类覆盖——在这种情况下,派生类实现将在对象完全初始化之前被调用

  • 您没有设置属性,该属性可能会通过KVO触发同一对象上的某些操作(该对象仍然未完全初始化)

如果您的
reset
方法(与设置属性无关)是私有的,则应该没有问题,除非有人在派生类中定义了同名的方法


为了进一步降低这种风险,您可以为您的私有方法使用命名约定,例如,
\u resetB

使用
init
方法向
self
发送消息是完全安全的。你在哪里听到别的?你可能听说过不要泄露自己。这是不同的。根据我的经验,如果我看到有人直接设置属性(不使用属性设置器)。我想这一定是有原因的。即使是在init方法中。@CrimsonChris,谢谢你的评论。我“听说不是这样”的地方是developer.apple.com。它说:“你应该总是直接从初始化方法中访问实例变量,因为……”你可以很容易地找到相关的网页。我更喜欢从不使用KVO(这是邪恶的),而只是让自定义设置为零安全。这比用nil检查自己的init方法更简单。这并不完全正确。风险还在于调用派生类中重写的方法;在这种情况下,派生类实现将在一个未完全初始化的对象内执行。@sergio Yeah这会导致问题,调用私有方法肯定会更安全(并且让公共方法调用私有方法),正如您在回答中所建议的,最终它归结为与KVO相同的问题。我唯一不明白的是谁否决了我的答案。。。但很高兴看到你在现场找到它!谢谢。@sergio看起来上下两位选民对我们的答案都改变了主意。是时候继续做一些有意义的事情了,比如说现实生活:)谢谢,你和@trojanfoe的答案都非常清楚和有用。我对objc(以及总体上的OO)相当陌生,有时我感觉到“模糊的不可触及的层”的存在,这让我想回到汇编语言……:)