Why is "self = [[Rectangle alloc] init]" in a class method BAD?

class-method, cocoa, objective-c

Solution

There is a fourth pattern....

(1) type mismatch is BAD.

(2) static reference to class yields method that won't behave correctly in subclasses

(3) dynamic reference to class means subclasses will be instantiated as subclass instances

(4)

+ (instancetype)rectangleOfColor:(NSColor *)color // Über-bestest evar!
{
     Rectangle *newInstance = [[self alloc] init];
     [newInstance setColor:color];
     return newInstance;
}

llvm added the `instancetype` keyword that says "yo! this method returns an instance of whatever class it was called on". Thus, if you were to subclass the above, you could:

RectangleSub *rs = [RectangleSub rectangleOfColor:[NSColor paisleyColor]];

But this would warn (beyond the awful color choice):

RectangleSub *rs = [Rectangle rectangleOfColor:[NSColor puceColor]];

Whereas the (id) return type would not warn in the second case.

Note that I also switched declared `newInstance` to be explicitly of type `Rectangle*`. This is more better, too, in that within the context of that method, `newInstance` can only be safely treated as a `Rectangle*`.

Problem

In the document "Objective-C Programming Language" by Apple, page 48 says: ``` + (Rectangle *)rectangleOfColor:(NSColor *) color { self = [[Rectangle alloc] init]; // BAD [self setColor:color]; return self; } + (id)rectangleOfColor:(NSColor *)color { id newInstance = [[Rectangle alloc] init]; // GOOD [newInstance setColor:color]; return newInstance; } + (id)rectangleOfColor:(NSColor *)color { id newInstance = [[self alloc] init]; // EXCELLENT [newInstance setColor:color]; return newInstance; } ``` One is bad, one is good, and the other is excellent. Why is that?

Original source