The Cocoa framework has a convention to always call self = [super init] in the init method of an inherited class, because [super init] may return a new instance.
What will happen if I do this?
@interface MyClass : NSObject /* or any other class */ {
int ivar_;
}
@end
@implementation MyClass
- (id)init {
ivar_ = 12345;
if ((self = [super init])) {
NSLog(@"ivar_'s value is %d", ivar_);
}
return self;
}
@end
In the case when [super init] returns a new instance, what will I see in the console? ivar_'s value is 0?
I can’t think of a way to check this myself, because I don’t know which class may return a new instance from its init method. Also, can’t seem to find explicit clarification for this scenario in the docs.
Could anyone help me out? Thanks!
Under normal circumstances, when you send
+allocto a class it returns a zeroed out instance of that class. It is already initialised in the sense that: a) it is a proper instance of that class, and b) all instance variables are zeroed out (numeric types are 0, C pointers are NULL, objects are nil, etc). However, no extra initialisation behaviour has been applied to the newly created instance — that’s the job of initialisers,-initbeing the most common of them. In particular, if your class inherits fromNSObjectthen[super init]doesn’t touch the newly created instance. So, in the code you’ve posted in your question,+allocis sent toMyClass, which returns a zeroed out instance. In particular,ivar_is 0-initis sent to the newly created instanceivar_ == 12345because of the assignment in-init, which could be rewritten asself->ivar_ = 12345. At this moment,selfpoints to the instance returned by+alloc[super init]is sent,ivar_isn’t touched since its superclass (NSObject) doesn’t know about it, and the return value is assigned toself. In fact, the return value is alreadyselfso nothing’s changedselfis different fromnil,NSLog()is called-initreturnsselfNow let’s consider that
[super init]returns an instance that’s different from the one returned by+alloc:+allocis sent toMyClass, which returns a zeroed out instance. In particular,ivar_is 0-initis sent to the newly created instanceivar_ == 12345because of the assignment in-init, which could be rewritten asself->ivar_ = 12345. At this moment,selfpoints to the instance returned by+alloc[super init]is sent and it decides to release the current instance and return a different one. The return value is assigned toselfso, from the current perspective,-initis now working on a different instance. The old instance was deallocated, hence that change toivar_is lost.ivar_contains whatever[super init]decides it should containselfis different fromnil,NSLog()is called-initreturnsself, which is not the same instance created by+allocYou can test this with the following code. Be warned that it’s just a quick example to illustrate my answer and it should not be used in production code.
The output is