为什么使用[ClassName alloc]而不是[[self class] alloc]?

时间:2010-08-24 18:30:40

标签: objective-c initialization allocation self

我正在阅读Mark Dalrymple的在Mac上学习Objective-C (仅在协议章节,所以仍然相对较新)并尝试解决问题:

为什么要用自己的名字引用一个类?如果我有一个名为Foo的课程,我为什么要写,比方说

[[Foo alloc] init]

而不是

[[[self class] alloc] init]

如果我有一个子类Bar,那么第一个选项不会使我无法编写

[[Bar alloc] init]

而第二种选择会允许吗?第一种选择什么时候会更好?

3 个答案:

答案 0 :(得分:26)

通常,在类方法中,您使用[[self alloc] init]。例如,为类编写便捷方法的规范方法是:

+ (id)fooWithBar:(Bar *)aBar
{
    return [[[self alloc] initWithBar:aBar] autorelease];
}

(注意,在类方法中,self引用类对象。)

但是,如果您确实需要[[Foo alloc] init]类的实例(而不是子类),则可以使用Foo(即显式类名)。

答案 1 :(得分:6)

只要你想要那个类,你就可以用它的名字来引用一个类。如果子类是从该类派生的,则同一方法中的self将代表该派生类。因此,如果要显式实例化超类,可以这样做。

有时候这可能有意义。要么强制子类重写该方法,以便返回它的类的实例。或者返回一个不同的类,比如在创建NSArray等时使用的占位符对象。

答案 2 :(得分:0)

我发现[ClassName alloc]和[self alloc]不相等的条件。我列出它以防其他人面临类似的情况。

//Option 1 
+ (NSInputStream *)streamWBlockWithArray:(NSArray *)dataArray 
{ return [[[self alloc] initWithArray:dataArray] autorelease]; } 
// Option 2 
+ (NSInputStream *)streamBlockWithArray:(NSArray *)dataArray
{ return [[[Block alloc] initWithArray:dataArray] autorelease]; }

如果我使用选项1,编译器给出了重复定义的编译器错误,则initWithArray的定义被标记为与+ [NSArray initWithArray]中的定义冲突。用[block alloc]替换[self alloc]后,编译器错误消失了。这可能只是一个编译器无法消除歧义,即使上下文看起来足够清楚。