Why is the current init method called but not the super's?


#1

Hi guys,

I’m new to iOS programming and Objective-C, so that’s why I have this beginner-level question.

So I was learning about the singleton in Chapter 9, and got confused by this sharedStore method:

+ (BNRItemStore *)sharedStore
{
    static BNRItemStore *sharedStore = nil;
    if (!sharedStore)
        sharedStore = [[super allocWithZone:nil] init];
    return sharedStore;
}

I understand everything except for this line: sharedStore = [[super allocWithZone:nil] init];

The point where I’m confused is, why am I calling the allocWithZone method of the super class but the init method in the current class? Shouldn’t it also be the one from super class?

This must be about the language itself, and I don’t really know what keyword to search about this question so I ask it here.

Any hint is appreciated!

Pine


#2

[super allocWithZone:nil] creates an instance of BNRItemStore; that’s why you need to call the init method of BNRItemStore on that instance.


#3

[quote]I understand everything except for this line: sharedStore = [[super allocWithZone:nil] init];

The point where I’m confused is, why am I calling the allocWithZone method of the super class but the init method in the current class? Shouldn’t it also be the one from super class?[/quote]

You’re calling super’s allocWithZone because you’ve overridden self’s allocWithZone to do nothing - it now just returns itself.

Then you’re calling self’s init as usual, because you still want to init your own class (every class no matter what is going to have its own designated init doing setup work for it). Recall that alloc creates the memory space for a new object - which you’ve effectively disabled for the singleton here - while init does the initial setup work.

If you didn’t call super’s alloc, you’d end up with an endless loop as allocWithZone calls sharedStore, and sharedStore calls allocWithZone.


#4

Excellent explanation but you can use more precise terminology.

Although classes too can be initialised, you meant you still want to init the instance of your own class…


#5

Thanks for the explanations guys.

So I do understand to alloc the memory I have to avoid using self’s alloc method but to use super’s, to avoid the endless loop. What I don’t understand is how the compiler understands that I did mean to use my self’s init method, but not the suer’s. You know, I didn’t mention self on the right side of the “=”:

The super here should be NSObject, so I was calling NSObject’s allocWithZone class method, and according to the doc it should return “A new instance of the receiver”. In my case which is the receiver? Is it super (NSObject) or sharedStore? (I think it’s super.)

If it’s super(NSObject) how did the compiler know I’m not calling NSObject’s init but my own?

If it’s sharedStore how did it know it’s the shareStore, which is on the left side of the “=”?

Thanks a lot!

Pine


#6

Yep, that’s a bit more interesting:

The compiler understands you’re calling self’s init because super (NSObject’s) default implementation of alloc will just return self.

It may all sound confusing, but this is a good example of the beauty of code snippets - just adapt the singleton code presented in the book and paste it wherever you’re going to need a singleton in the future. With basic pattern code like this, you’re really copying and pasting stuff like this all the time, so don’t go crazy thinking about code you know works.


#7

[quote=“jgelling”]Yep, that’s a bit more interesting:

The compiler understands you’re calling self’s init because super (NSObject’s) default implementation of alloc will just return self.

It may all sound confusing, but this is a good example of the beauty of code snippets - just adapt the singleton code presented in the book and paste it wherever you’re going to need a singleton in the future. With basic pattern code like this, you’re really copying and pasting stuff like this all the time, so don’t go crazy thinking about code you know works.[/quote]

But definitely good to know NSObject’s default implementation of alloc is returning self.

Thanks!