Http://www.cocoachina.com/macdev/objc/2011/0124/2602.html
In the class implementation of objective-C, we often see the two keywords "self" and "super". Taking the previous OOP language experience as an example, C ++ assumes that self is equivalent to this, super is equivalent to calling the parent class method, which seems easy to understand. BelowCodeFor example:
@ Interface person: nsobject {
Nsstring * Name;
}
-(Void) setname :( nsstring *) yourname;
@ End
@ Interface personme: person {
Nsuinteger age;
}
-(Void) setage :( nsuinteger) age;
-(Void) setname :( nsstring *) yourname andage :( nsuinteger) age;
@ End
@ Implementation personme
-(Void) setname :( nsstring *) yourname andage :( nsuinteger) Age {
[Self setage: Age];
[Super setname: yourname];
}
@ End
Int main (INT argc, char * argv []) {
NSAID utoreleasepool * Pool = [[NSAID utoreleasepool alloc] init]
Personme * Me = [[personme alloc] init];
[Me setname: @ "ASDF" andage: 18];
[Me release];
[Pool drain];
Return 0;
}
There are two simple classes on the top. The setage class in the sub-class personme is called and the setname in the parent class is called. These codes seem easy to understand and there is no problem.
Then I add two lines to the setname: andage method:
Nslog (@ "Self 'class is % @", [self class]);
Nslog (@ "Super 'class is % @", [super class]);
In this way, the two classes will be created during the call. Let's guess, what will be printed? Based on the previous OOP language experience, the output is as follows:
Self's class is personme
Super's class is person
However, after compiling and running, you can find that the result is:
Self's class is personme
Super's class is personme
Self's class is the same as expected. How is super's class also personme?
Truth
Self is a hidden parameter of the class, pointing to the class of the method currently called, and another hidden parameter is _ cmd, representing the selector of the current class method. Here we only focus on this self. What is super? Super is not a hidden parameter. It is just a "compiler indicator". It points to the same message receiver as self. Take the above Code as an example, whether [self setname] or [Super setname] is used, the recipient of the message "setname" is a personme * me object. The difference is that super tells the compiler that when the setname method is called, the method of the parent class should be called instead of the method in this class.
When using self to call a method, it will start from the method list of the current class. If not, it will be searched from the parent class. When using super, you can find it from the method list of the parent class. Then, call the method of the parent class.
One more step
How is this mechanism implemented at the underlying layer? In fact, when calling a class method, the compiler will convert the method call into a C function method call. Apple's objcruntimeref says:
Sending messages
When it encounters a method invocation, the compiler might generate a call to any of several functions to perform the actual message dispatch, depending on the handler, the return value, and the arguments. you can use these functions to dynamically invoke
Methods From your own plain c code, or to use argument forms not permitted by nsobject's perform... Methods. These functions are declared in/usr/include/objc/objc-runtime.h.
■ Objc_msgsend sends a message with a simple return value to an instance of a class.
■ Objc_msgsend_stret sends a message with a data-structure return value to an instance
A class.
■ Objc_msgsendsuper sends a message with a simple return value to the superclass of an instance of a class.
■ Objc_msgsendsuper_stret sends a message with a data-structure return value to the superclass of an instance of a class.
We can see that one of the above four methods will be called. Because the _ Stret series and the two without _ Stret are similar, we only focus on the objc_msgsend and objc_msgsendsuper methods. When [self setname] is used, the objc_msgsend function is used. First, let's look at the Function Definition of objc_msgsend:
Id objc_msgsend (ID thereceiver, Sel theselector ,...)
The first parameter is the message receiver, and the second parameter is the selector of the specific class method called, followed by the variable parameter of the selector method. Let's ignore this variable parameter. Taking [self setname:] as an example, the compiler will replace it with the function call that calls objc_msgsend, where thereceiver is self and theselector is @ selector (setname :), this selector is the setname from the list of methods of the current self class. When it is found, it passes the corresponding selector.
When [Super setname] is used, the objc_msgsendsuper function is used. For more information, see the Function Definition of objc_msgsendsuper:
Id objc_msgsendsuper (struct objc_super * super, Sel op ,...)
The first parameter is the structure of objc_super, and the second parameter is similar to the selector of the above class method. Let's take a look at what the structure of objc_super is:
Struct objc_super {
Id Explorer;
Class superclass;
};
It can be seen that this struct contains two members, one is the aggreger, which is similar to the first parameter of objc_msgsend above, and the second member is the record of what the parent class of the super class is, take the above Code as an example. When the compiler encounters [Super setname:] In the setname: andage method in personme, it starts to do the following:
-
- Construct the objc_super struct. At this time, the first member variable of the struct is personme * me, which is the same as self. The second member variable superclass refers to the class person, because the superclass of personme is the person.
- Call the objc_msgsendsuper method to pass the sel of this struct and setname. The operations in the function are similar to the following: Find the setname selector from the list of superclass Methods pointed to by the objc_super struct, and then call the selector with objc_super-> aggreger, the objc_msgsend function may also be used. However, the first parameter thereceiver is objc_super-> aggreger, and the second parameter is from objc_super-> superclass.
Selector found in
The Calling mechanism is basically like this. From the above analysis, let's look back at the initial code. What is the process when [self class] and [super class] are output.
when using [self class], self is personme, when objc_msgsend is used, the first parameter is the consumer er, that is, self, which is also the personme * me instance. The second parameter, You need to first find the selector of the class method, first start from the personme class, no, and then find it in the personme parent class person, no, go to nsobject, the parent class of person, and find the class method in the nsobject class level by level. The class method of nsobject
, returns the Cycler category. Therefore, the personme is output here.
When using [super class], convert it to the objc_msgsendsuper method. First, construct the structure of objc_super. The first member variable is self, and the second member variable is person. Then, find the selector of the class and find it in superclass, that is, person. No, then, find it in the parent class of person. The result is still found in nsobject. Use the objc_msgsend (objc_super-> extends er, @ selector (class) function internally to call the function.
[Self class] The call time is the same. In this case, the consumer er is still personme * me, so here the return is also personme.