3

我想做这个:

[[ClassA new] addObject:[[ClassA new] addObject:[ClassA new]]];

但编译器返回:

"error: invalid use of void expression"

有没有办法做到这一点?就像在java中一样:

ClassA = new ClassA( new ClassA( new ClassA()));
4

5 回答 5

5

真正的问题是它-[ClassA addObject:]很可能有一个返回类型 void,所以你不能将该表达式嵌套为外部-addObject: 调用的参数。例如,请参阅文档-[NSMutableArray addObject:]- 方法签名是- (void) addObject:(id)anObject. 如果您习惯于使用另一种语言(尤其是 Java)的不同行为,这可能会让您措手不及。另请注意,-removeObject:返回void,而不是被删除的对象。

此外,+new除非被覆盖,否则每个人都错过了继承的点——请参阅+[NSObject new]. 然而,使用+new是“过时的”,并且+alloc/-init...是首选。一个原因是因为无论如何+new调用-init,您必须创建一个 +new... 变体来匹配类中的每个 -init...。到那时,你会得到很多不必要的代码来解决一个非问题。我个人+new很少使用,只有当我知道我只使用-init.

由于您来自 Java 背景,如果您对为什么 Objective-C 使用 alloc/init 而不是像 Java、C++ 等这样的新方法感到好奇,请查看这个 SO 问题。

于 2009-06-24T18:13:49.953 回答
2

您的代码片段仅new在 ClassA 上定义的方法是类方法而不是实例方法并且 ClassA 还实现了addObject:您想要的选择器的情况下才能工作。我不确定您的方法是如何定义的,但要使其正常工作,您需要在 ClassA 上定义以下方法:

+ (ClassA *)new;
- (ClassA *)objectByAddingObject:(ClassA *)newObject;

选择new器需要返回一个指向新 ClassA 对象的指针,因此它的实现可能包含类似于

return [[ClassA alloc] init];

并且addObject:选择器需要在另一个 ClassA 中存储一个 ClassA 对象,然后返回带有添加子对象的新对象:

self.object = newObject;
return self;

请注意,由于对 的嵌套调用addObject:,该方法必须返回 (ClassA *) 而不是 (void),这通常是这种情况。您可能需要考虑重构,以便查看以下内容:

[[ClassA alloc] initWithObject:[[ClassA alloc] initWithObject:[[ClassA alloc] init]]];
于 2009-06-24T16:47:28.667 回答
2

问题不在于 new,而在于 addObject,它是一个 void 返回方法。

你的代码:

[[ClassA new] addObject:[[ClassA new] addObject:[ClassA new]]];

将更等同于以下 Java 代码:

ClassA = new ClassA()->AddObject( new ClassA()->AddObject( new ClassA() ) );

出于同样的原因,这将失败,即 AddObject 返回 void,而不是 self。

最重要的是,代码显然会失败,因为 new 是一个“所有权”方法,这意味着您根据内存管理规则获得创建对象的所有权,但是您将它传递给 addObject 然后忘记它,所以没有剩下一个来释放它。此外,您甚至不保存对最终对象的引用。

适当的代码更像是:

ClassA* c2 = [ClassA classA];
[c2 addObject:[ClassA classA]];
ClassA* c = [ClassA classA];
[c addObject:c2];

其中 ClassA 的 classA 方法实现为:

(ClassA*) classA
{
    return [[ClassA new] autorelease];
}

或者,您可以添加进一步的方法:

(ClassA*) classAWithObject: (ClassA*) inObject
{
    ClassA* c = [ClassA classA];
    [c addObject:inObject];
    return c;
}

然后写:

ClassA* c = [ClassA classAWithObject:[ClassA classAWithObject:[ClassA classA]]];

这对于 Cocoa/Objective C 的执行方式非常真实,并且等效于您的 Java 代码,并且实际上遵守内存管理规则。

于 2009-06-25T03:21:10.983 回答
0

在目标 C 中,通常要创建和初始化一个新对象,您需要执行以下操作:

[[ClassA alloc] init]

alloc,为对象分配内存,并初始化它。

我不知道 ClassA 的详细信息,但我猜你想用以下代码替换你的代码:

[[[ClassA alloc] init] addObject:[[[ClassA alloc] init] addObject:[[ClassA alloc] init]]]

尽管仔细查看您的 java 示例,您似乎正在将新的 ClassA 实例传递给构造函数,但以下可能更等效。(这假设 ClassA 有一个名为 'initWithObject' 的构造函数。)

ClassA *myClass = [[ClassA alloc] initWithObject:[[ClassA alloc] initWithObject:[[ClassA alloc] init]];
于 2009-06-24T16:46:20.273 回答
-1

编辑:以下不是必需的,因为new继承自NSObject. 有关详细信息,请参阅Quinn Taylor 的答案,当您在那里时,请为它的正确性投票。:)

@interface ClassA
{
    //...
}
+(ClassA)new;
//...
@end

@implementation ClassA
+(ClassA)new { return [[ClassA alloc] init]; }
//...
@end
于 2009-06-24T16:49:04.203 回答