类方法的对象分配?

时间:2009-11-05 16:16:43

标签: objective-c cocoa

我只是好奇这是对的还是不好的做法? (即使用类方法来分配/初始化实例)?我是否正确地认为我必须在main()中释放实例作为我唯一可以访问实例指针的地方?

// IMPLEMENTATION
+(id) newData {
    DataPoint *myNewData;
    myNewData = [[DataPoint alloc] init];
    return myNewData;
}

// MAIN
DataPoint *myData;
myData = [DataPoint newData];
... stuff
[myData release];

编辑:

也应该

myNewData = [[DataPoint alloc] init];

是(或无关紧要)

myNewData = [[self alloc] init];

EDIT_002:

奇怪的是,当我添加autorelease时,我得到了......

alt text

EDIT_003:

@Dave DeLong,最后一个问题,你的说法是什么:

+(id) dataPoint {
    return [[[self alloc] init] autorelease];
}

而不是(你将在主要版本中发布)

+(id) new {
    return [[self alloc] init];
}
欢呼加里

4 个答案:

答案 0 :(得分:14)

根据命名约定,您应该将其命名为+dataPoint。分析器向你发射的原因是(按照惯例),使用“new”的类方法应返回具有+1保留计数的对象。你正在返回一个带有+0(自动释放)保留计数的对象,因此违反惯例。

正如在@ Peter的回答中提到的,要创建一个空对象,通常使用[ClassName className]方法完成。例如:[NSArray array][NSData data][NSString string]等。因此,您要做的就是将其重命名为[DataPoint dataPoint],然后将其实施为return [[[self alloc] init] autorelease];

最好使用[self alloc],因为它可以转换为子类。 IE,如果你创建一个MutableDataPoint子类,那么(如果你使用[self alloc])执行[MutableDataPoint dataPoint]会返回MutableDataPoint,而如果你把它留给[DataPoint alloc],它会回来作为DataPoint对象(因为这就是你要分配的东西)。 (在旁注中,self指的是在方法的上下文中操作的对象。例如方法,它是实例。对于类方法,它是Class对象本身)

编辑:

如果您确实希望类方法返回具有+1保留计数的对象,那么(按照惯例),您只需要将其称为+new(即DataPoint * p = [DataPoint new];)。但是,+new方法的使用似乎已经或多或少地被废弃,+alloc/-init...或类便利方法是有利的选择。

编辑#2(Re:Edit_003):

我个人更喜欢前者(+dataPoint),但仅仅因为+new不常见,我不必记住-release对象。但是,任何一个都是完全可以接受和正确的。

答案 1 :(得分:5)

你可以写得很整齐;

+ (id)dataPoint {
    return [[[MyDataPoint alloc] init] autorelease];
}

注意:您仍应编写init方法;这种类方法通常用于方便。此外,如果您没有GC,则应根据内存管理规则自动释放返回值。

编辑重命名为+ dataPoint,由Dave更正。

答案 2 :(得分:2)

您的静态方法newData是一个非常好的做法,您可以在整个Cocoa API中看到类似的方法(例如,[NSString string][NSData data])。

你应该做的唯一事情(如果你没有使用垃圾收集器)是将它添加到自动释放池。惯例是,如果从alloc,new,copy或mutableCopy获取新对象,则需要自己保留/释放它。如果您通过任何其他方式获得对象(您的newData方法将符合“其他方式”),那么假设该对象已添加到自动释放池中,并且无需管理记住你自己。

至于[DataPoint alloc][self alloc],他们都编译,并且从我所知道的内容同样有效。我自己来自Java背景,我建议[DataPoint alloc],因为你处于静态上下文(self类似于java this,不应该真的存在于非 - 静态背景)。当然,我对Objective-C很新,而且Objective-C不是Java,所以你的milage可能会有所不同。

答案 3 :(得分:1)

  

EDIT_002:

     

奇怪的是,当我添加autorelease时,我得到了......

一点也不奇怪。阅读它的内容:

  1.   

    Method返回一个具有+1保留计数(拥有引用)的Objective-C对象

    您将方法命名为newDatanew方法返回拥有的引用。

  2.   

    对象已发送-autorelease消息

    烨。就在那里。

  3.   

    对象作为拥有引用返回给调用者(传递给调用者的单个保留计数)

    new方法(例如newData)会返回拥有引用,这意味着该new方法的调用方会收到拥有引用。调用者应该拥有此对象。代替...

  4.   

    对象以+0(非拥有)保留计数

    返回给调用者

    您自动释放了该对象,否定了所有权。即使你应该这样做,你也不再返回拥有的引用。这总结在最后一面旗帜中:

  5.   

    具有+0保留计数的对象[sic]返回给调用者,其中预期+1(拥有)保留计数

    调用者应该期望拥有该对象,因为它来自new方法,但它没有,因为你自动释放它。因为调用者认为它拥有该对象,所以它应该稍后释放或自动释放它,但是因为你已经这样做了,所以这将是一个过度释放。

  6. 解决方案是遵守Cocoa命名约定并纠正这种期望违规。这意味着两种解决方案之一:

    1. 保持名称不变,不要自动释放该对象。
    2. 更改方法的名称,使其不是new方法,并自动释放该对象。
    3. 我会做#2,因为它更常见,通常对呼叫者的工作也少一些。