Possible Duplicate:
why does initializing开发者_高级运维 subclasses require calling the super class's same init function?
I really can't understand the role of super in initializing an object. For example, having this (example — not written by me) code:
@implementation MyObject
- (id) init
{
if([super init]){
return self;
} else {
return nil;
}
}
@end
What [super init] actually does? I'm confused, can't get the point
It is necessary to ensure correct initialisation of inherited instance variables from the super class of MyObject
.
Since Objective-C is object oriented you can inherit from other classes. When you inherit from other classes you can intercept messages and get to decide if you pass them on to the class you inherit from. In the case of init it is almost always important to do self = [super init]
or use the designated init method of the class to make sure the object is created correctly. Imagine if in MyObject in your init method you create an NSMutableArray
that your class uses but init was never called because someone else inherited from your class and never called [super init]
. You would then have nil references or either a bad pointer every where you attempted to used your NSMutableArray
. The reason why it is important to set self
equal to [super init]
is the value of self may change such as in error recovery.
//this is valid
-(id)init
{
if((self = [super init]))
{
if(someInitializationFails)
{
[self release];
self = nil;
}
}
return self;
}
Wil Shipley recommends this (from 2009):
- (id)init;
{
if (!(self = [super init]))
return nil;
// other stuff
return self;
}
But why assign super init's return to self?
Matt Gallagher's article attempts to explain it...
-- Quote:
If you remember back at the start, I said that the initWithString: part of a typical [[MyClass alloc] initWithString:@"someString"] invocation is converted into an objc_msgSend call:
MyClass *myObject2 = objc_msgSend(myObject1, initSelector, @"someString");
So by the time we get to the inside of the method, self already has a value; its value is myObject1 (i.e. the allocated object, as returned from the [MyClass alloc] call. This is essential because without it, the super invocation wouldn't be possible — the self value is used by the compiler to send the invocation:
[super init];
becomes:
objc_msgSendSuper(self, @selector(init));
Yes, self already has a value when your initializer starts. In fact, it is almost guaranteed to be the correct, final value.
-- Unquote
Essentially, I think a lot of people are left confused as to what each init method's 'self' is pointing to exactly, up through the superclass chain.
The answer to this riddle is implied in Apple's Objective-C Programming Language doc, under the section titled Designated Initializers:
Note that B version of init sends a message to self to invoke the initWithName: method. Therefore, when the receiver is an instance of the B class, it invokes the B version of initWithName:, and when the receiver is an instance of the C class, it invokes the C version.
Or, in other words, the 'self' variable points to the our instance that is being initialized. Again to reemphasize, all of these init methods up through the superclass chain are inherited by our instance, and as such, the 'self' variable in them points to our instance (unless explicitly changed) .
Am I right? Of course!
精彩评论