views:

93

answers:

3

I'm trying to understand the use of the keyword self Let's say that I have two classes one called AppDelegate and one called Photo. Photo is my "model" class in the MVC paradigm and AppDelegate is the controller.In the init method of the Photo class below. Who is self referring to?

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

    }

    return self;
}
+4  A: 

self is the object that received the message. In instance methods, it's the instance that received the message; in class methods, it's the class that received the message.

So, in init, self is the instance you're initializing—the instance that something sent an init message to, probably (hopefully) immediately after receiving it from alloc.

If you make a convenience constructor, such as this:

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

that's a class method, so in this method, self will refer to the Foobar class:

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

The implementation:

  1. Sends an alloc message to self (the class); assuming you didn't override alloc (and you normally wouldn't), it will hit NSObject's implementation, which will respond by creating and returning an uninitialized instance.
  2. Sends an init message to that instance; that message hits your init instance method, which calls up to super, does whatever initialization is necessary, and returns self (which, in init, is the instance).
  3. Sends an autorelease message to that instance; again, you normally wouldn't override this, so it hits NSObject's implementation, which adds the instance to the nearest autorelease pool and returns it.
  4. Finally, returns the freshly allocated, initialized, and autoreleased instance.
Peter Hosey
I finally understand this concept. Thank you very much Mr. Hosey :D
lampShade
A: 

In your example code, **self** is referring to the instance of the object where you have defined init. It is analogous to 'this' in C++.

mobibob
+1  A: 

self is the object you're sending a message to. For instance, if you call something like [foo doSomething], in the doSomething method, self will be equal to foo. It's a hidden argument passed to methods.

It might be confusing that self is not read-only in Objective-C. For instance, in the initializer, as you may see, you actually override self:

if( self = [super init] ){

This is because [super init] is actually entitled to return a completely different object. However, you're just changing the value of a variable passed as an argument; you're not changing the value in the scope that called the method.

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

In this example, in the second case, foo and bar may actually point to two distinct objects. Both alloc and init return a pointer to an object, and technically they could be different (though the only one you'll want to keep is the one init returned, since the object pointed to by alloc's return value isn't ready for use).

As mentioned above, self is actually one of two hidden arguments methods receive. The other hidden argument is named _cmd and contains the selector used to call the method. You rarely need it.

This means that whenever you see this:

id bar = [foo doSomethingWithInt:5];

You could (symbolically) resolve it to a function call similar to this:

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

So self is really just an argument.

zneak
If you replace “`Foo_doSomething`” with `objc_msgSend`, that's exactly what the compiler does. ☺
Peter Hosey
@Peter Hosey There's more magic involved, though. `objc_sendMsg` has to lookup the selector for the object's class.
zneak
zneak: Huh? There is no selector for a class, and the selector for the method is passed in by the compiler (it's the second argument, just as it is to the method implementation).
Peter Hosey
Oh, I see what you meant: If you assign the method implementation to `Foo_doSomething`, then you can use code such as that to call it directly. Right on.
Peter Hosey