让我们考虑一下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”。因此,您尽职尽责地重写了子类中指定的初始值设定项,但您调用了超级的辅助初始值设定项之一:
@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:
。您覆盖了指定的初始值设定项,因此它调用您的方法。你的方法过滤掉 Bob,然后调用 super 的辅助初始化器,initWithArray:
…它转身并再次调用您指定的初始化器覆盖。无限递归。堆栈溢出。你会得到分段违规核心转储的忧郁。
这就是为什么你总是使用 super 的指定初始化器。