18

I'm reading through Mark Dalrymple's Learn Objective-C on the Mac (only at the chapter on Protocols, so still relatively newbish) and trying to figure something out:

Why would you ever reference a class by its own name? If I had a class called Foo, why would I ever want to write, say,

[[Foo alloc] init]

and not

[[[self class] alloc] init]

If I had a subclass Bar, wouldn't the first option invalidate me from writing

[[Bar alloc] init]

whereas the second option would allow it? When would the first option be better?

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
Nick Sweet
  • 2,030
  • 3
  • 31
  • 48
  • 2
    Just a note here for posterity. Given the answers below and the scenarios they talk about, the reference to '[self class]' in '[[[self class] alloc] init]' is unnecessary, since 'self' is already referring to the class object. The only scenario where that line can be used as it is, is if you are creating another object of the Foo class in an instance method of Foo - say '- (void)createAnotherFancyObject;' like so "Foo *bar = [[[self class] alloc] init]" – Dev Kanchen Jun 22 '11 at 04:59

3 Answers3

28

Generally, within a class method, you do use [[self alloc] init]. For example, the canonical way to write a convenience method for a class is:

+ (id)fooWithBar:(Bar *)aBar
{
    return [[[self alloc] initWithBar:aBar] autorelease];
}

(Note that in a class method, self refers to the class object.)

However, you would use [[Foo alloc] init] (that is, an explicit class name) if you actually want an instance of the Foo class (and not a subclass).

mipadi
  • 398,885
  • 90
  • 523
  • 479
  • So just to be clear, `[[[self class] alloc] init]` is a redundant way to write `[[self alloc] init]`? I'm going through a similar guide and saw this line, and it seems like just using `self` would be enough. – NHDaly Mar 06 '13 at 18:16
  • 3
    @NHDaly: Yeah -- in a class method, `self` refers to `Class` instance. – mipadi Mar 06 '13 at 22:16
7

You refer to a class by it's name whenever you want exactly that class. If a subclass was derived from that class, a self in the same method would represent that derived class instead. Hence, if you want to explicitly instantiate a superclass, this could be done.

There are occasions where this might make sense. Either to force the subclass to override the method in order to return an instance of it's class. Or to return a different class, like a placeholder object used in the creation of an NSArray etc.

Max Seelemann
  • 9,344
  • 4
  • 34
  • 40
0

I found a condition under which [ ClassName alloc ] and [ self alloc ] were not equivalent. I am listing it in case others are faced with a similar situation.

//Option 1 
+ (NSInputStream *)streamWBlockWithArray:(NSArray *)dataArray 
{ return [[[self alloc] initWithArray:dataArray] autorelease]; } 
// Option 2 
+ (NSInputStream *)streamBlockWithArray:(NSArray *)dataArray
{ return [[[Block alloc] initWithArray:dataArray] autorelease]; }

If I use option 1, the compiler was giving a compiler error of duplicate definitions the definition of initWithArray was being flagged as conflicting with the definition from + [ NSArray initWithArray ]. The compiler error went away after I replaced [ self alloc ] by [ Block alloc ]. This is probably just a compiler unable to disambiguate even though the context seems clear enough.

nishant
  • 736
  • 1
  • 12
  • 22