2010-09-11 83 views
0

我想了解关键字的使用self假设我有两个类,一个叫做 AppDelegate,另一个叫Photo。照片是我在MVC范例中的“模型”类,AppDelegate是控制器。下面的Photo类的init方法。谁是自我指涉?谁是自我指涉?

-(id) init 
{ 
    if(self = [super init]){ 
     [self setCaption:@"Default Caption"]; 
     [self setPhotographer:@"Default Photographer"]; 

    } 

    return self; 
} 

回答

4

self是收到该消息的对象。在实例方法中,它是接收消息的实例;在类方法中,它是接收该消息的类。

所以,在initself是你初始化,实例的实例的东西发送的init消息,可能是(希望)从alloc收到后立即。

如果你犯了一个有用的构造方法,比如这个:

//Returns a new, autoreleased Foobar instance. 
+ (id) foobar 

这是一个类的方法,所以在这个方法中,self将参考Foobar类:

{ 
    return [[[self alloc] init] autorelease]; 
} 

实现:

  1. 发送alloc消息给self(全班);假设你没有覆盖alloc(你通常不会),它会触及NSObject的实现,它会通过创建并返回一个未初始化的实例来进行响应。
  2. 向该实例发送init消息;该消息将触发你的实例方法,该方法调用super,不管初始化是否必要,并返回self(其中init是实例)。
  3. 向该实例发送autorelease消息;再次,你通常不会重写这个,所以它碰到NSObject的实现,它将实例添加到最近的autorelease池并返回它。
  4. 最后,返回新分配,初始化和自动释放的实例。
+0

我终于明白了这个概念。非常感谢Hosey先生:D – lampShade 2010-09-11 03:11:47

0

在您的示例代码中,**self**指的是您已定义init的对象的实例。它类似于C++中的'this'。

1

self是您要发送消息的对象。例如,如果您调用类似[foo doSomething]的方法,则在doSomething方法中,self将等于foo。这是一个传递给方法的隐藏参数。

可能令人困惑的是self在Objective-C中不是只读的。例如,在初始化,因为你可能会看到,你实际上覆盖self

if(self = [super init]){ 

这是因为[super init]实际上是有权返回一个完全不同的对象。然而,你只是改变了作为参数传递的变量的值;你没有改变调用该方法的范围中的值。

Foo* foo = [[Foo alloc] init]; 
// ... may be different of... 
Foo* foo = [Foo alloc]; 
Foo* bar = [foo init]; 

在这个例子中,在第二种情况下,foobar实际上可以指向两个不同的对象。 allocinit都返回一个指向一个对象的指针,从技术上讲,它们可能与不同(尽管只有你想保留的那个是返回的那一个init,因为alloc指向的对象的返回值不是准备启用)。

如上所述,self实际上是方法接收的两个隐藏参数之一。另一个隐藏的参数被命名为_cmd并包含用于调用该方法的选择器。你很少需要它。

这意味着,当你看到这一点:

id bar = [foo doSomethingWithInt:5]; 

你可以(象征),它解析为一个类似的函数调用:

id bar = Foo_doSomething(foo, @selector(doSomethingWithInt:), 5); 

所以self实际上只是一个说法。

+0

如果用'objc_msgSend'替换“'Foo_doSomething'”,那正是编译器所做的。 ☺ – 2010-09-11 04:32:30

+0

@Peter Hosey虽然有更多的魔法参与。 'objc_sendMsg'必须查找对象类的选择器。 – zneak 2010-09-11 04:54:41

+0

zneak:嗯?没有类的选择器,并且该方法的选择器被编译器传入(这是第二个参数,就像它的方法实现一样)。 – 2010-09-11 05:11:23