Let's say I create my class and its init
method. Why should I call and return value of superclass init
assigned to self? Which cases it covers?
I would appreciate examples why would I need it for Cocoa superclass and non-Cocoa.
Let's say I create my class and its init
method. Why should I call and return value of superclass init
assigned to self? Which cases it covers?
I would appreciate examples why would I need it for Cocoa superclass and non-Cocoa.
Source
Implementing The Designated Initializer
**
self
** Inside a method, self is an implicit local variable. There is no need to declare it, and it is automatically set to point to the object that was sent the message. (Something like this in Android programming.) Typically, self is used that an object can send a message to itself. Example here:
**
super
** When we overriding a method, we want to keep what method of the superclass is doing and have your subclass add something new on that. To make it easier, there is compiler directive in Objective-C called super. How does super work? Usually when you send a message to an object, the search for a method of that name starts in the object's class. If there is no such method, the search continues in the superclass of the object. The search will continue up the inheritance hierarchy until a suitable method is found. (If it gets to the top of the hierarchy and no method is found, an exception is thrown). When we send a message to super, we are sending message to self, but the search for the method skips the object's class and start at the superclass. In the above case, we send init message to super. This calls NSObject's init method.
I know it is a little bit late for my answer, but I cannot stop myself from posting a link which I found very useful in clearing my doubt about this problem.
Matt Gallagher: What does it mean when you assign [super init] to self?
EDIT: As per the comments, here are the essential points in the link
To understand why
self=[super init];
we need to consider many points. Let's tackle it one by one.What is
self
Every method has two hidden parameters:
self
and_cmd
. So the method callis changed by compiler into a function call like this
Why do we need self?
The reality is that the compiler uses the
self
parameter to resolve any reference to an instance variable inside a method.Suppose that we have a method
setValueToZero
andvalue
is an instance variable of the class it belongs to, then the implementationwill be converted by the compiler into a function like this
Do
self
already have a value wheninit
is called?Following is an example of a typical object creation and initialization.
Here, by the time we get into the
initWithString
method, self will have the newly allocated object as its value (i.e., the return value from[MyClass alloc]
). In fact, it is almost guaranteed to be the correct, final value.Why
self = [super init];
?It is because
[super init]
is permitted to do one of the three things:self
pointer doesn't change) with inherited instance values initialized.nil
, indicating failure.In the first case, assignment has no effect on
self
. In the third case, the initialization has failed,self
is set tonil
and it is returned.The reason behind assignment to
self
is with the second case. Consider the followingWe want the conversion from
to
to act on the correct value and thus we have to change the value of
self
.When would
[super init]
return a different object?In one of the following situations
[NSNumber numberWithInteger:0]
always returns the global "zero" object)In all but the final case, continuing to initialize the returned object if it changes is a mistake — the returned object is already completely initialized and isn't necessary related to your class anymore. So a better init approach will be as follows
Conclusion
You don't need to assign
[super init]
toself
to make most classes work. In some obscure cases, it is actually the wrong thing to do.So why do we continue to assign to
self
? It's the traditional template for an initializer, and although it's wrong in some cases, it is right in other cases which have been written to expect this approach.You mean why
rather than
Two reasons:
Edited in response to Michael's comment:
No. Instance variables are accessed relative to the self pointer, so in the following:
self has clearly got to point to the right block of memory i.e. the one you are going to return.
That could be a problem. If I subclassed NSNumber and [super init] decided to return an NSString (which it could - there's nothing to stop it) that would clearly be a disaster. Whatever super returns from -init must be "compatible" with the subclass in the sense of providing space for ivars and being further subclassible or it's a horrendous bug (unless, of course, the problem is documented). So, in general, you don't need to worry about checking the class. However, do read the documentation. See for instance the section on subclassing NSString in NSString's docs.
Basically every Objective-C class is a subclass. It's either some class you've specified or NSObject.
In the subclass (your class that you're working on) you call self = [super init]
What this basically does is calls the super class's (the ones I mentioned above) init method (the constructor) and assigns it to the current class.
This makes sure that the superclasses' initializing method is called.
Now for If(self) This basically checks if the above piece of code worked.
This is done to insure that if you call some Instance Variable of the super class, you'll be able to do so.
In most cases, setting self to [super init] does nothing since [super init] will wind up returning self anyway. There are some rare cases, however, where [super init] will return something different. It may return nil if it fails to initialize the superclass for some reason or it may decide to return a completely different object.
Because you have to initialize the object somehow, and presumably you want to do any initialization a superclass required be done, since you're descending from it.