为什么不能在指定初始化调用基类的辅助初始化?(Why can't a designated

2019-09-16 10:07发布

根据该文件,在Objective-C类的指定初始化必须调用基类的指定初始化。

另一条规则是,二次初始化必须调用自己的类的指定初始化。

但是,如果第二条规则是其次的,为什么不能在指定初始化调用基类的辅助初始化? 该基地二次初始化最终调用自己的水平的DI,所以对象仍然会被正确的初始化,对不对?

所不同的似乎是谁选择默认值遗漏变量 - 你或你的基类。

Answer 1:

让我们考虑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自动拒绝字符串“鲍勃”。 所以,你尽职尽责地重写指定初始化你的子类,但你叫超的二次初始化之一:

@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: 。 你推翻了指定初始化,所以它调用你的方法。 你的方法过滤掉鲍勃,然后调用超类的二次初始化, initWithArray: ...这转了一圈,并再次调用您指定的初始化覆盖。 无限递归。 堆栈溢出。 你得到的分割违章-核心转储布鲁斯。

这就是为什么你总是使用超类的指定初始化。



Answer 2:

如果指定的初始化是调用二次初始化在自己的类,那么就无法放送指定的初始化的作用。 指定初始化的要点是这样一个子类实现者知道单初始化他/她可以覆盖所有其他初始化时将漏斗通过。

如果在子类中的指定初始化是调用一个非指定初始化其超类中,则超初始化可能会掉头,并调用另一个初始化的。 由于方法调度的动态性质,它不能限制只在调用它的级别实现的方法。 这一呼吁是非常有可能是子类的优先选项之一,这将漏斗到子类的指定初始化,导致无限递归。



文章来源: Why can't a designated initializer call a secondary initializer in its base class?