Objective-C initializers and overriding self
I have a question about writing your own init methods in objective-c. I've read a few different books and have seen a couple of ways to do it but the consensus is the right way to do it is like this:
- (id)init
{
self = [super init];
if(self!=nil)
{
}
return self;
}
I'm a little confused about the line "self = [super init]". My understanding is that, there's no guarantee that [super init] will return the class that you expect it to. I think this is called "class clusters". But in the normal case, where it does return the class you expect it to, if I set self to point to a class that is returned to me, aren't I just saying that self is referring to an object of a different class rather than the class that I'm in the init method of?
To summarize, why set self to be the superclass vs the actual class I'm in?
From a blog I read:
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 dif开发者_Go百科ferent object with inherited instance values initialized. 3) Return nil, indicating failure. In the first case, the assignment has no effect on self...
"The assignment has no effect on self" is what confuses me. Why does it have no effect? If I set something = to something else, shouldn't that have an effect?
There are different opinions on the proper way to write -init
methods. There are two reasons that would make you think that self = [super init]
is a good idea. (The assignment itself isn't anything special; Objective-C considers self
to be a hidden parameter of the method, and you can reassign to parameters. The changed self
only applies for the remainder of the method.)
Superclass -init
returns instance of different class
As you suggested, some classes use the "class cluster" pattern. However, in the most common implementation of this pattern, it's the -alloc
method on the base class that is likely to return an instance of a different class, and it's all the -init...
methods on the placeholder class that are likely to return an instance of a different class. self = [super init]
is not useful here.
Superclass -init
returns a different instance of the same class
This is the reason that self = [super init]
is recommended. Some classes have logic that allows -init
to return a different instance than the one that it was called on. For example, some singleton classes in the Cocoa framework do this. But in almost every case, you need to know this behavior of the superclass in order to properly subclass it. Here's an argument by Wil Shipley that self = [super init]
isn't actually very useful, because either [super init]
returns self
anyway, or the class you're subclassing is sufficiently complicated that reassigning self and then continuing with the initialization won't work anyway.
To summarize, why set self to be the superclass vs the actual class I'm in?
This is the Apple suggested way to do things, specifically due to the case of class clusters, as you say.
In general, you should not worry about the fact that self
might be of a different class in the "normal" case.
self
simply identifies the object you are, not the class (the class is actually a different object in the runtime). If you think of OO inheritance properties, it is at the same time an object of its class and of its superclass (if it is clear what I am trying to say). There is no contradiction in the "normal" case, since the value of self
does not change.
Also, you can think of self
as a special pointer to your object. In the cluster case, self
can change, that is the reason why it can happen that its class change.
Hope this helps clarifying things. You will also find an interesting reading in this article by Wil Shipley.
精彩评论