在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;
}
一个是坏的,一个是好的,另一个是优秀的。那是为什么?
答案 0 :(得分:17)
还有第四种模式......
(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*
。
答案 1 :(得分:9)
+ (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]
。请注意,此处self
再次在类上调用,因为+alloc
是一个类方法。
出于同样的原因,所有init…
和方便的创建者方法都应该返回id
。它允许子类返回子类的对象,而不会让编译器发疯。
答案 2 :(得分:6)
在第一种情况下,您将self
指针(应指向Rectangle
类对象)分配给Rectangle
的实例。这绝对不正确。
在第二种情况下,您需要对要实例化的类进行硬编码 - 在这种情况下为Rectangle
。
在第三种情况下,您允许类的标识确定实例的类,而不是在代码中明确指定它。然后,如果您的Dodecahedron
类需要使用相同的代码,则不需要更改类名。