为什么是一个类的方法BAD“自我= [[矩形的alloc] INIT]”?(Why is “self

2019-08-17 15:46发布

在文件“Objective-C编程语言”苹果,第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;
}

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

Answer 1:

还有第四种模式....

(1)类型不匹配是坏的。

(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*



Answer 2:

+ (Rectangle *)rectangleOfColor:(NSColor *) color
{
    self = [[Rectangle alloc] init]; // BAD
    [self setColor:color];
    return self;
}

在类方法self指类,而不是它的一个实例对象。


+ (id)rectangleOfColor:(NSColor *)color
{
    id newInstance = [[Rectangle alloc] init]; // GOOD
    [newInstance setColor:color];
    return newInstance;
}

如果矩形将被继承(MyFancyRectangle),这仍然会返回一个普通的矩形对象,而

+ (id)rectangleOfColor:(NSColor *)color
{
    id newInstance = [[self alloc] init]; // EXCELLENT
    [newInstance setColor:color];
    return newInstance;
}

将返回MyFancyReactangle好象叫喜欢MyFancyReactangle *r = [MyFancyReactangle rectangleOfColor:[UIColor redColor]][self alloc]被称为上sublass。 请注意,这里self再次呼吁类,如+alloc是一个类的方法。

出于同样的原因,所有init…方便的创建者方法应该返回id 。 它允许子类没有编译器要疯了返回subclass'ed对象。



Answer 3:

在第一种情况下,您指定self指针(它应指向Rectangle类对象)的实例Rectangle 。 这是绝对不正确。

在第二个,你硬代码的类实例化- Rectangle在这种情况下。

第三,你让全班同学的身份,以确定类的实例,而不是在代码中显式指定它。 然后,如果你的Dodecahedron类需要使用相同的代码,它不会需要改变类的名称。



文章来源: Why is “self = [[Rectangle alloc] init]” in a class method BAD?