self
在 Objective-C中是什么意思?我应该在何时何地使用它?它类似于this
Java吗?
6 回答
self
指您正在使用的当前类的实例,是的,它类似于this
Java。
如果要对该类的当前实例执行操作,可以使用它。例如,如果您正在为一个类编写一个实例方法,并且您想在同一个实例上调用一个方法来执行某些操作或检索一些数据,您可以使用self
:
int value = [self returnSomeInteger];
这也经常用于实例上的访问器方法(即 setter 和 getter),尤其是 setter 方法,如果它们实现额外的功能而不仅仅是设置实例变量的值,那么您不必重复该代码并当您要设置该变量的值时结束,例如:
[self setSomeVariable:newValue];
最常见的用途之一self
是在类的初始化期间。示例代码可能如下所示:
- (id)init
{
self = [super init];
if(self!=nil) {
//Do stuff, such as initializing instance variables
}
return self;
}
这会调用超类的(通过super
)初始化程序,这是链式初始化在类层次结构中发生的方式。然而,返回值随后设置为self
,因为超类的初始化程序可能返回与超类不同的对象。
self
is an implied argument to all Obj-C methods that contains a pointer to the current object in instance methods, and a pointer to the current class in class methods.
Another implied argument is _cmd
, which is the selector that was sent to the method.
Please be aware that you only get self
and _cmd
in Obj-C methods. If you declare a C(++) method, for instance as a callback from some C library, you won't get self or cmd.
For more information, see the Using Hidden Arguments section of the Objective-C Runtime Programming guide.
是的,它与 Java 中的“this”完全相同——它指向“当前”对象。
Two important notes:
The class itself, e.g.
UIView
(I'm NOT talking about aUIView
object) is itself an object, and there is aself
associated with it. So for example, you can referenceself
in a class method like this:// This works +(void) showYourself { [self performSelector: @selector(makeTheMostOfYourself)]; } // Class method! +(void) makeTheMostOfYourself { }
Note that the compiler does NOT raise any warnings or errors, even if the
self
you mean to reference is an object and not a class. It is VERY easy to cause crashes this way, for example:// This will crash! +(void) showYourself { [self performSelector: @selector(makeTheMostOfYourself)]; } // Object method! -(void) makeTheMostOfYourself { } // This will crash too! -(void) showYourself2 { [self performSelector: @selector(makeTheMostOfYourself2)]; } // Class method! +(void) makeTheMostOfYourself2 { }
Sadly, this makes class methods a bit harder to use, which is unfortunate because they are a valuable tool for encapsulation through information hiding. Just be careful.
Wow, that many half-correct answers and misleading hints. This let me answer the Q even there is a accepted answer for years:
First of all: It is really hard to compare a concept of messaging/calling in the context of an early binding, static typing language as Java with a late binding, dynamically typing languages as Objective-C. At one point this will break. I would say: No, this is not similiar, since the typing and dispatching concepts of both language are fundamental different so nothing can be similar to the other one. However, …</p>
Then we should differ between the "two sides" of self
.
A. Using self
When you use it in a message, it is simply an object reference as any other:
[self doSomething];
[anotherObject doSomething];
Technically both lines works identically (accept of having a different receiver, of course). This especially means, that the first line does not lead to an execution of a method inside the class of self
, because self
does not necessarily refer to "that class". As every message inside Objective-C (single exception: messages to super
)this can lead to the execution of a method in a subclass:
@interface A : NSObject
- (void)doSomething;
- (void)doAnotherThing;
@end
@implementation
- (void)doSomething
{
[self doAntoherThing];
}
- (void)doAnotherThing
{
NSLog( @"A" );
}
@interface B : A
- (void)doSomething; // Not necessary, simply as a marker
@end
@implementation B
- (void)doAnotherThing
{
NSLog( @"B" );
}
In a code like this
B *b = [B new;]
[b doSomething];
The line
[self doAnotherThing];
in class A
will lead to the execution of -doAnotherThing
(B
), because messages to self
are late bound as every other message. The result on the console will b "B", not "A". Using self
as a receiver you should not think of a single special rule. There is completely none.
(And the above example is a very good example for using self
in class methods, because the same situation can occur on class methods. Using the class itself breaks polymorphism, what is one of the worst idea at all in OOP. DO use self
in class methods, too.)
B. Getting self
What is self
pointing to? It points to the object to whom the message is sent that caused the execution of the current method.
Having …</p>
…[someObject doSomething]… // some object is a reference to an instance object
… as a message, a method is called, in the most simple case …</p>
- (void)doSomething
{ … }
In such a case, self
can point to an instance of the class, the method belongs to. And it can point to an instance of a subclass, the method belongs to, too. You don't know. (And this information is preserved using self
to send a message as explained above.)
If the message is sent to a class object, self
points to the class object, that was the receiver of the message. This is completely analogous. Therefore it is possible that self
points to a subclass object:
@interface A : NSObject
+ (void)doSomething;
+ (void)doAnotherThing;
@end
@implementation
+ (void)doSomething
{
[self doAntoherThing];
}
+ (void)doAnotherThing
{
NSLog( @"A" );
}
@interface B : A
- (void)doSomething; // Not necessary, simply as a marker
@end
@implementation B
+ (void)doAnotherThing
{
NSLog( @"B" );
}
Having this classes
…[A doSomething]…
self
inside -doSomething
(A
) points to the class object of B
. Therefore [self doAnotherThing]
of B
(!) is executed. This is clearly different from
+ (void)doSomething
{
[A doAntoherThing];
}
The latter version causes relevant harm to the principles of OOP.
As a side note it is possible that self
inside a class method of a root class points to an instance object of the root class or any subclass. You have to keep this in mind, when writing categories on NSObject
.
self is an object pointer to the current instances dispatch table. It is an implicit first argument to every member function of an object, and is assigned when that function is called.
In functions like init, you need to be careful that when you call the super class init you reassign self to be the return value as the super class init may redefine what self points to.
super is similar to self except it points to the superclass dispatch table.