8

在 Apple 的文档“Objective-C Programming Language”中,第 48 页说:

+ (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;
}

一个是坏的,一个是好的,一个是优秀的。这是为什么?

4

3 回答 3

17

还有第四种模式......

(1) 类型不匹配是 BAD。

(2) 对类的静态引用产生在子类中行为不正确的方法

(3) 动态引用类意味着子类将被实例化为子类实例


(4)

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

llvm 添加了instancetype关键字“哟!此方法返回调用它的任何类的实例”。因此,如果您要对上述内容进行子类化,您可以:

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

但这会警告(除了可怕的颜色选择):

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

而 (id) 返回类型在第二种情况下不会发出警告。

请注意,我还切换声明newInstance为显式类型Rectangle*。这也更好,因为在该方法的上下文中,只能newInstance安全地视为Rectangle*.

于 2013-03-15T16:13:27.600 回答
9
于 2013-03-15T15:59:14.393 回答
6

在第一种情况下,您将self指针(应该指向Rectangle类对象)分配给Rectangle. 这是绝对不正确的。

第二,你硬编码一个类来实例化——Rectangle在这种情况下。

在第三个中,您允许类的标识来确定实例的类,而不是在代码中明确指定它。然后,如果您的Dodecahedron班级需要使用相同的代码,则不需要更改班级名称。

于 2013-03-15T15:56:37.293 回答