self super
当使用 self 调用方法时,会从当前类的方法列表中开始找,如果没有,就从父类中再找;而当使用 super 时,则从父类的方法列表中开始找。然后调用父类的这个方法。
Messages to self and super
Objective-C provides two terms that can be used within a method definition to refer to the object that performs the method—self
and super
.
Suppose, for example, that you define a reposition
method that needs to change the coordinates of whatever object it acts on. It can invoke the setOrigin::
method to make the change. All it needs to do is send a setOrigin::
message to the same object that the reposition
message itself was sent to. When you’re writing the reposition code, you can refer to that object as either self
or super
. The reposition
method could read either:
- reposition |
{ |
... |
[self setOrigin:someX :someY]; |
... |
} |
or:
- reposition |
{ |
... |
[super setOrigin:someX :someY]; |
... |
} |
Here, self
and super
both refer to the object receiving a reposition
message, whatever object that may happen to be. The two terms are quite different, however. self
is one of the hidden parameters that the messaging routine passes to every method; it’s a local variable that can be used freely within a method implementation, just as the names of instance variables can be. super
is a term that substitutes for self
only as the receiver in a message expression. As receivers, the two terms differ principally in how they affect the messaging process:
-
self
searches for the method implementation in the usual manner, starting in the dispatch table of the receiving object’s class. In the example above, it would begin with the class of the object receiving the reposition message. -
super
is a flag that tells the compiler to search for the method implementation in a very different place. It begins in the superclass of the class that defines the method wheresuper
appears. In the example above, it would begin with the superclass of the class where reposition is defined.
Wherever super
receives a message, the compiler substitutes another messaging routine for the objc_msgSend
function. The substitute routine looks directly to the superclass of the defining class—that is, to the superclass of the class sending the message to super
—rather than to the class of the object receiving the message.
An Example: Using self and super
The difference between self
and super
becomes clear when using a hierarchy of three classes. Suppose, for example, that we create an object belonging to a class called Low
. The superclass of Low
is Mid
; the superclass of Mid
is High
. All three classes define a method called negotiate
, which each class uses for its own purpose. In addition, Mid
defines an ambitious method called makeLastingPeace
, which itself employs the negotiate
method. The classes and those methods are illustrated in Figure 2-2.
Suppose that the implementation of makeLastingPeace
(in the Mid
class) uses self
to indicate the object to send the negotiate
message to:
- makeLastingPeace |
{ |
[self negotiate]; |
... |
} |
When a message is sent to a Low
object to perform the makeLastingPeace
method, makeLastingPeace
sends a negotiate
message to the same Low
object. The messaging routine finds the version of negotiate
defined in Low
, the class of self
.
However, if the implementation of makeLastingPeace
instead uses super
as the receiver,
- makeLastingPeace |
{ |
[super negotiate]; |
... |
} |
the messaging routine finds the version of negotiate
defined in High
. It ignores the class (Low
) of the object that received the makeLastingPeace
message and skips to the superclass of Mid
, because Mid
is where makeLastingPeace
is defined. Neither implementation finds the Mid
version of negotiate
.
As this example illustrates, super
provides a way to bypass a method that overrides another method. Here, the use of super
enabled makeLastingPeace
to bypass the Mid
version of negotiate
that redefined the High
version of that method.
Not being able to reach the Mid
version of negotiate
, as just described, may seem like a flaw, but under the circumstances it’s intentional:
-
The author of the
Low
class intentionally overrode theMid
version ofnegotiate
so that instances ofLow
(and its subclasses) would invoke the redefined version of the method instead. The designer ofLow
didn’t wantLow
objects to perform the inherited method. -
The author of the
Mid
methodmakeLastingPeace
, in sending thenegotiate
message tosuper
(as shown in the second implementation), intentionally skipped over theMid
version ofnegotiate
(and over any versions that might be defined in classes likeLow
that inherit fromMid
) to perform the version defined in theHigh
class. The designer of the second implementation ofmakeLastingPeace
wanted to use theHigh
version ofnegotiate
and no other.
The Mid
version of negotiate
could still be used, but it would take a direct message to a Mid
instance to do so.
Using super
Messages to super
allow method implementations to be distributed over more than one class. You can override an existing method to modify or add to it and still incorporate the original method in the modification:
- negotiate |
{ |
... |
return [super negotiate]; |
} |
For some tasks, each class in the inheritance hierarchy can implement a method that does part of the job and passes the message on to super
for the rest. The init
method, which initializes a newly allocated instance, is designed to work like this. Each init
method has responsibility for initializing the instance variables defined in its class. But before doing so, it sends an init
message to super
to have the classes it inherits from initialize their instance variables. Each version of init
follows this procedure, so classes initialize their instance variables in the order of inheritance:
- (id)init |
{ |
self = [super init]; |
if (self) { |
... |
} |
} |
It’s also possible to concentrate core functionality in one method defined in a superclass and have subclasses incorporate the method through messages to super
. For example, every class method that creates an instance must allocate storage for the new object and initialize its isa
variable to the class structure. Allocation is typically left to the alloc
and allocWithZone:
methods defined in the NSObject
class. If another class overrides these methods (a rare case), it can still get the basic functionality by sending a message to super
.
Redefining self
super
is simply a flag to the compiler telling it where to begin searching for the method to perform; it’s used only as the receiver of a message. But self
is a variable name that can be used in any number of ways, even assigned a new value.
There’s a tendency to do just that in definitions of class methods. Class methods are often concerned not with the class object, but with instances of the class. For example, many class methods combine allocation and initialization of an instance, often setting up instance variable values at the same time. In such a method, it might be tempting to send messages to the newly allocated instance and to call the instance self
, just as in an instance method. But that would be an error. self
and super
both refer to the receiving object—the object that gets a message telling it to perform the method. Inside an instance method, self
refers to the instance; but inside a class method, self
refers to the class object. This is an example of what not to do:
+ (Rectangle *)rectangleOfColor:(NSColor *) color |
{ |
self = [[Rectangle alloc] init]; // BAD |
[self setColor:color]; |
return self; |
} |
To avoid confusion, it’s usually better to use a variable other than self
to refer to an instance inside a class method:
+ (id)rectangleOfColor:(NSColor *)color |
{ |
id newInstance = [[Rectangle alloc] init]; // GOOD |
[newInstance setColor:color]; |
return newInstance; |
} |
In fact, rather than sending the alloc
message to the class in a class method, it’s often better to send alloc
to self
. This way, if the class is subclassed, and the rectangleOfColor:
message is received by a subclass, the instance returned is the same type as the subclass (for example, the array
method of NSArray
is inherited by NSMutableArray
).
+ (id)rectangleOfColor:(NSColor *)color |
{ |
id newInstance = [[self alloc] init]; // EXCELLENT |
[newInstance setColor:color]; |
return newInstance; |
} |
引用:
http://web2.0coder.com/archives/305