Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Self = [super init]

Tags:

objective-c

If self is able to store the base class instance then when we are returning the self, how it transformed to derived instance.

like image 569
balusu Avatar asked May 25 '26 00:05

balusu


2 Answers

Here's what I think you're asking: suppose we have a base class Base and a subclass Derived. If -[Derived init] calls -[Base init] and -[Base init] returns a different instance, won't that different instance be an instance of Base and not Derived and thus inappropriate? For example, the new object won't have the instance variables that Derived might have added to the class.

The answer is that Base is not allowed to do that. If it replaces the original instance, it must do so in a manner that respects the dynamic type of that original instance. For example, it might do something like:

// Re-allocate with 100 extra bytes
id newSelf = NSAllocateObject([self class], 100, [self zone]);
[self release];
self = newSelf;
// ... continue to initialize ...
return self;

Or, it might dynamically generate a new subclass of the original class and then allocate a new instance of that new class.

NSString* newClassName = [NSString stringWithFormat:"%@_DynamicSubclass", NSStringFromClass([self class])];
Class newClass = objc_allocateClassPair([self class], [newClassName UTF8String], 0);
// ... further configure the new class, by adding instance variables or methods ...
objc_registerClassPair(newClass);
id newSelf = [newClass alloc];
[self release];
self = newSelf;
// ... continue to initialize ...
return self;

Whatever it does, it has to satisfy the constraint that the new instance is suitable to be used wherever the old instance was, based on its dynamic type.

like image 191
Ken Thomases Avatar answered May 27 '26 14:05

Ken Thomases


self is a hidden method argument:

// this Objective-C
- (id) initWithString:(NSString*)str;

// gets implemented like this C function would be
- (objc_object*) Foo_initWithString(Foo* self, SEL _cmd, NSString* str);

It is a pointer to memory (allocated with alloc) that is already big enough to hold the most derived object. The most derived class calls super's init, which also calls its super's init and so each class in hierarchy gets its constructor called.

So, nothing is transformed — it is just a pointer to an already existing object, you can either return it (99.9% of the time) or substitute another object instead.

Note there is a second hidden argument, the selector _cmd, which in this case equals to @selector(initWithString:). You can also use it if you need current method name e.g. for debug logging.

like image 28
hamstergene Avatar answered May 27 '26 16:05

hamstergene



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!