繁体   English   中英

为什么在类方法BAD中“self = [[Rectangle alloc] init]”?

[英]Why is “self = [[Rectangle alloc] init]” in a class method BAD?

在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;
}

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

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

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

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

如果Rectangle将被子类化(MyFancyRectangle),那么仍然会返回一个普通的Rectangle对象

+ (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 它允许子类返回子类的对象,而不会让编译器发疯。

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

在第二种情况下,您需要对要实例化的类进行硬编码 - 在这种情况下为Rectangle

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM