[英]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.