0

Briefly, I have a class implementation:

@implementation ClassB: ClassA
-(id) init {
    if (self = [super init]) {
        ...
    }
    return self;
}
@end

And a category, in two variants:

1:

@implementation ClassA (ClassA_Category)
+(id) alloc {
    if ([self isEqual: [ClassA class]]) {
        return [ClassB alloc];
    } else {
        return [super alloc];
    }
}
@end

2:

@implementation ClassA (ClassA_Category)
+(id) alloc {
    return [[ClassB superclass] superclass] alloc];
}
@end

The question is about this simple initialization:

ClassA *aObj = [[ClassA alloc] init];

For the first category variant, init of ClassB is called, but for the second case - doesn't.

Why ? Does these two alloc constructions have the same meaning ?

Martin Babacaev
  • 6,240
  • 2
  • 19
  • 34

1 Answers1

2

[[ClassB superclass] superclass] will be ClassA's superclass (probably NSObject — I'm going to assume so for the rest of this answer). So the second variant is specifically equivalent to [NSObject alloc]. This means the object that you send init to is just an NSObject, not a ClassA or a ClassB.

In the first variant, [ClassB alloc] executes ClassA's implementation (through inheritance), which calls [super alloc] in cases where the class is not ClassA (which ClassB isn't), which executes the default implementation of alloc. This allocates a ClassB, which is then sent init.

I think your confusion is caused by the assumption that [[self superclass] theCurrentMethod] is equivalent to [super theCurrentMethod]. It's not. The super keyword keeps the receiver (self) the same, but just skips over the current class when resolving that message to a particular implementation. But when you explicitly send a message to [self superclass], the superclass itself is the receiver.

Chuck
  • 234,037
  • 30
  • 302
  • 389