-4

There are three class Question,Choiceand Blank,and Question is the super class of Choice and Blank.

Then, I write some methods as follows:

- (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"];
}

and then:

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

the output is:

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

and I can't understand why [super init] did not be executed?

lxyzk
  • 11
  • 3
  • 3
    Because `if([self isMemberOfClass:[Question class]])` is true and it returns self before it gets to return `[super init];`, That was a wild stab in the dark. Try changing `isMemberOfClass` to `isKindOfClass:` – Popeye Oct 16 '15 at 14:11
  • 1
    Which class is this code in? – rmaddy Oct 16 '15 at 14:11
  • @CalebKleveter What difference would that make? – rmaddy Oct 16 '15 at 14:12
  • 1
    @CalebKleveter Yes, you are incorrect. The order of the methods in the source file is irrelevant. – rmaddy Oct 16 '15 at 14:16
  • @CalebKleveter I'm not sure whether you're being sarcastic or not. – Popeye Oct 16 '15 at 14:16
  • @Popeye, I am not being sarcastic. – Caleb Kleveter Oct 16 '15 at 14:17
  • the `[super init];` probably will be invoked if the first if-else statement evaluated as `FALSE` in the `-initWithQuestionType:` method; but because your log line in your instance's `–init` method (not in the super's) therefore that line will be called when the `[[Question alloc] init];` or `[Question new];` performed, but I'm not sure about your question, btw. – holex Oct 16 '15 at 15:13

1 Answers1

0

Your [super init] method is being called:

  1. [Question initWithQuestionType] is called.
  2. The first if is true, so it's entered.
  3. The question type is "choice" so [Choice initWithQuestionType:] is called.
  4. As Choice does not override -initWithQuestionType:, this will call [Question initWithQuestionType:] again.
  5. This time the if is false, so it's not entered, and [super init] is being called.

This is being shown in your log messages (add an another log call before the [super init] method, to prove this).

However it's a very confusing and difficult to maintain factory method, and it's much easier to use a class factory method, as below. That way your init methods will be much more straight-forward and easier to maintain.

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

Also consider using an enum to represent the type, rather than a string (quicker/more efficient).

l00phole
  • 622
  • 3
  • 8
  • While this may be useful info it does not answer the question. – rmaddy Oct 16 '15 at 14:17
  • @l00phole it would probably be better if you explain why it is completely incorrect instead of just saying it is completely incorrect. I currently agree with `rmaddy` but I am open to change. – Popeye Oct 16 '15 at 14:19
  • @rmaddy OK, taken a stab at it. – l00phole Oct 16 '15 at 14:50
  • Yes,`[super init]` method is being called. And the method being called is belong to Question's super class. I can't understand why. – lxyzk Oct 17 '15 at 11:40
  • @lxyzk You have created very complex code that is difficult to understand. There is no need to do this; just use the class-level factory method approach as shown in my answer. That way the implementation of the `init` methods becomes trivial. – l00phole Oct 17 '15 at 12:38
  • @l00phole Very grateful for your advice – lxyzk Oct 19 '15 at 02:08