13

In a book, I saw that if a subclass is overriding a superclass's method, we may have

self = [super init];

First, is this supposed to be done in the subclass's init method?

Second, I wonder why the call is not just

[super init];

? I mean, at the time of calling init, the memory is allocated by alloc already (I think by [Foobar alloc] where Foobar is the subclass's name. So can't we just call [super init] to initialize the member variables? Why do we have to get the return value of init and assign to self? I mean, before calling [super init], self should be pointing to a valid memory allocation chuck... so why assigning something to self again?

(if assigning, won't [super init] just return self's existing value?)

nonopolarity
  • 146,324
  • 131
  • 460
  • 740

4 Answers4

11

So why assign the value returned from [super init] to self? Looking at a typical initializer method:

 - (id)initWithString:(NSString *)aString {
     self = [super init];
     if (self)
     {
         instanceString = [aString retain];
     }
     return self; }

Why do we assign [super init] to self here?

The textbook reason is because [super init] is permitted to do one of three things:

  1. Return its own receiver (the self pointer doesn't change) with inherited instance values initialized.
  2. Return a different object with inherited instance values initialized.
  3. Return nil, indicating failure.

In the first case, the assignment has no effect on self and the instanceString is set on in the original object (the line instanceString = [aString retain]; could have been the first line of the method and the result would be the same).

In the third case, the initialization has failed. self is set to nil, no further action is taken and nil is returned.

The rationale for assigning to self is associated with the second case: if the returned object is different, we want the:

instanceString = [aString retain]; which gets converted to

self->instanceString = [aString retain]; to act on the correct value,

so we have to change the value of self to point to this new object.

hoping this helps...

From Cocoa with Love

pgb
  • 24,813
  • 12
  • 83
  • 113
Ankit Srivastava
  • 12,347
  • 11
  • 63
  • 115
  • interesting... so if `self` was pointing to some memory allocated, and then `self` is set to `nil`, then it is like... making itself as some sort of phantom? For example, if it is a `Duck` object, so `duck` points to valid memory allocated, with member variables, but now, when `self` is set to `nil`, then it sort of becomes a phantom, as right now it has no member variables any more (not pointing to any memory allocated), and all that is left are the methods, the ability to run code without any "substance"? – nonopolarity Apr 13 '12 at 11:45
  • NO object should release itself... the normal way to do it is by calling -dealloc.. – Ankit Srivastava Apr 13 '12 at 11:54
3

A classic example of returning a different object from -init is in implementing a class cluster - an abstract interface with multiple concrete implementers providing different storage or algorithms. +[NSString alloc] returns an instance of NSPlaceholderString. The initialisers of the placeholder instance inspect their parameters, release the placeholder string and return an initialised instance of a concrete NSString subclass.

2

It is possible the superclass might decide the object can't be initialised properly and return nil as a failure. If you don't assign nil to self your init method will carry on under the assumption that the parent class has correctly initialised the object.

It is also possible for the parent class to also return a completely different object if it wants.

mttrb
  • 8,297
  • 3
  • 35
  • 57
2

Understand that the object is already alloced and self points to a memory.

Now [super init] does the initialization part.

1) If initialization is successful self points to same object before initialization

2) If initialization is failure init function returns nil and self = nil. Now we can check whether object is initialized and if yes do our magic by this code

 if(self = [super init]){
  // do our magic
 }

IT is just like we use an imageView, we normally use

UIImageView imgView = [[UIImageView alloc] init];

imgView will only have non nil value if both alloc and init is succesful.

Krishnabhadra
  • 34,169
  • 30
  • 118
  • 167