根据文档,Objective-C中类的指定初始值设定项必须调用其基类的指定初始值设定项。

另一个规则是,辅助初始化程序必须调用自己类的指定初始化程序。

但是,如果遵循第二条规则,为什么指定的初始化程序不能在其基类中调用辅助初始化程序?这个基本的辅助初始化程序将最终调用其自身级别的D.I.,因此该对象仍将被正确初始化,对吗?

区别似乎在于谁为缺失的变量选择默认值-您还是您的基类。

最佳答案

让我们考虑NSSet。它具有指定的初始化程序:

- (id)initWithObjects:(const id *)objects count:(NSUInteger)cnt {
   // initialization code here
   return self;
}

它还具有一些辅助初始化程序,例如:
- (id)initWithArray:(NSArray *)array {
    NSUInteger count = array.count;
    id objects[count];
    [array getObjects:objects range:NSMakeRange(0, count)];
    return [self initWithObjects:objects count:count];
}

现在,您需要NSSet的子类,该子类会自动拒绝字符串“Bob”。因此,您有义务重写子类中的指定初始值设定项,但是您调用super的辅助初始值设定项之一:
@implementation BobRejectingSet

- (id)initWithObjects:(const id *)objects count:(NSUInteger)count {
    NSMutableArray *array = [[NSMutableArray alloc] initWithCount:count];
    for (NSUInteger i = 0; i < count; ++i) {
        if (![objects[i] isEqual:@"Bob"]) {
            [array addObject:objects[i]];
        }
    }
    return [super initWithArray:array];
}

当您这样做时会发生什么:
BobRejectingSet *noBobs = [[BobRejectingSet alloc] initWithArray:someObjects];

由于您没有覆盖initWithArray:,因此程序会调用-[NSSet initWithArray:],后者会调用指定的初始化程序initWithObjects:count:。您覆盖了指定的初始化程序,因此它将调用您的方法。您的方法会过滤掉Bobs,然后调用super的辅助初始化程序initWithArray:…,它会转过来并再次调用您指定的初始化程序覆盖。无限递归。堆栈溢出。您会得到“分割-违反-核心转储”的忧郁。

这就是为什么您始终使用super的指定初始化程序的原因。

关于objective-c - 为什么指定的初始化程序不能在其基类中调用辅助初始化程序?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10057461/

10-11 22:43
查看更多