为什么指定的初始值设定项不能在其基类中调用辅助初始值设定项?

Hal*_*alt 9 inheritance coding-style objective-c designated-initializer

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

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

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

差异似乎是谁选择缺失变量的默认值 - 您或您的基类.

rob*_*off 9

我们考虑一下NSSet.它有一个指定的初始化程序:

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

它还有一些辅助初始化器,如下所示:

- (id)initWithArray:(NSArray *)array {
    NSUInteger count = array.count;
    id objects[count];
    [array getObjects:objects range:NSMakeRange(0, count)];
    return [self initWithObjects:objects count:count];
}
Run Code Online (Sandbox Code Playgroud)

现在你想要一个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];
}
Run Code Online (Sandbox Code Playgroud)

执行此操作时会发生什么:

BobRejectingSet *noBobs = [[BobRejectingSet alloc] initWithArray:someObjects];
Run Code Online (Sandbox Code Playgroud)

由于你没有覆盖initWithArray:,程序调用-[NSSet initWithArray:],调用指定的初始化程序,initWithObjects:count:.您覆盖指定的初始化程序,因此它会调用您的方法.您的方法过滤掉Bobs,然后调用super的辅助初始化程序,initWithArray:...转过来并再次调用指定的初始化程序覆盖.无限递归.堆栈溢出.你得到了分段违规 - 核心倾销的蓝调.

这就是为什么你总是使用超级指定的初始化程序.