为什么我的代码没有进入[super init]函数?

时间:2015-10-16 14:08:33

标签: ios objective-c class-cluster

有三个课程QuestionChoiceBlankQuestionChoiceBlank的超类。

然后,我写了一些方法如下:

- (instancetype)initWithQuestionType:(NSString *)questionType
{
    NSLog(@"**class:%@",[self class]);
    if([self isMemberOfClass:[Question class]])
    {
        self = nil;
        if([questionType isEqualToString:@"choice"])
        {
            NSLog(@"--class:%@",[self class]);
            self = [[Choice alloc] initWithQuestionType:questionType];
            NSLog(@"++class:%@",[self class]);
        }
        else
        {
            self = [[Blank alloc] initWithQuestionType:questionType];
        }

        return self;
    }

    return [super init];
}

- (instancetype)init
{
    NSLog(@"Init!");

    return [self initWithQuestionType:@"unKnow"];
}

然后:

Question *question = [[Question alloc] initWithQuestionType:@"choice"];

输出是:

2015-10-16 20:58:50.278 initSample[3687:161396] **class:Question
2015-10-16 20:58:50.279 initSample[3687:161396] --class:(null)
2015-10-16 20:58:50.279 initSample[3687:161396] **class:Choice
2015-10-16 20:58:50.280 initSample[3687:161396] ++class:Choice

我无法理解为什么[super init]没有被执行?

1 个答案:

答案 0 :(得分:0)

正在调用您的[super init]方法:

  1. [Question initWithQuestionType]被召唤。
  2. 第一个if为真,因此已输入。
  3. 问题类型为"choice",因此调用[Choice initWithQuestionType:]
  4. 由于Choice未覆盖-initWithQuestionType:,因此会再次致电[Question initWithQuestionType:]
  5. 这次if为false,因此未输入,且[super init]正在调用。
  6. 这会显示在您的日志消息中(在[super init]方法之前添加另一个日志调用,以证明这一点。)

    然而,这是一种非常混乱且难以维护的工厂方法,并且使用类工厂方法更容易,如下所述。这样,您的init方法将更直接,更易于维护。

    + (Question *)questionWithType:(NSString *)type
    {
        if ([type isEqualToString:@"choice"])
            return [[Choice alloc] init];
        else
            return [[Blank alloc] init];
    }
    

    还可以考虑使用enum来表示类型,而不是字符串(更快/更有效)。