I want to do this:
[[ClassA new] addObject:[[ClassA new] addObject:[ClassA new]]];
but the compiler returns:
"error: invalid use of void expression"
Is there a way to do it? like in java:
ClassA = new ClassA( new ClassA( new ClassA()));
I want to do this:
[[ClassA new] addObject:[[ClassA new] addObject:[ClassA new]]];
but the compiler returns:
"error: invalid use of void expression"
Is there a way to do it? like in java:
ClassA = new ClassA( new ClassA( new ClassA()));
In objective C, generally to create, and initialise a new object you do something along the lines of the following:
[[ClassA alloc] init]
alloc, allocates memory for the object, and init initialises it.
I don't know the details ClassA, but I'd guess you want to replace you're code with the following:
[[[ClassA alloc] init] addObject:[[[ClassA alloc] init] addObject:[[ClassA alloc] init]]]
Although taking a closer look at your java example, you seem to be passing new ClassA instances through to the constructer, the following may be more equivalent. (This assumes ClassA has a constructor called 'initWithObject'.)
ClassA *myClass = [[ClassA alloc] initWithObject:[[ClassA alloc] initWithObject:[[ClassA alloc] init]];
Your code snippet will only work assuming that the new
method defined on ClassA is a class method, rather than an instance method, and that ClassA also implements the addObject:
selector that does what you want it to. I'm not sure how your methods are defined, but for this to work, you'd need the following method definitions on ClassA:
+ (ClassA *)new;
- (ClassA *)objectByAddingObject:(ClassA *)newObject;
The new
selector would need to return a pointer to a new ClassA object, so its implementation would probably contain something similar to
return [[ClassA alloc] init];
And the addObject:
selector will need to store a ClassA object within another ClassA, then return the new object with the added sub-object:
self.object = newObject;
return self;
Note that because of the nested calls to addObject:
, that method has to return (ClassA *) rather than (void), as is usually the case. You might want to consider refactoring so that you're looking at something like:
[[ClassA alloc] initWithObject:[[ClassA alloc] initWithObject:[[ClassA alloc] init]]];
edit: The following is not necessary, since new
is inherited from NSObject
. See Quinn Taylor's answer for details, and while you're there upvote it for being correct. :)
@interface ClassA
{
//...
}
+(ClassA)new;
//...
@end
@implementation ClassA
+(ClassA)new { return [[ClassA alloc] init]; }
//...
@end
The real problem is that -[ClassA addObject:]
very likely has a return type of void, so you can't nest that expression as the argument to the outer -addObject
: call. For an example, see the documentation for -[NSMutableArray addObject:]
— the method signature is - (void) addObject:(id)anObject
. This can catch you off guard if you are used to different behavior in another language, particularly Java. Also note that -removeObject:
returns void
, not the object that was removed.
In addition, everyone is missing the point that +new
is inherited unless overridden — see +[NSObject new]
. However, using +new
is "out of vogue", and +alloc/-init...
is preferred. One reason is that since +new
calls to -init
anyway, you must create a +new... variant to match each -init... in the class. By that point, you get a lot of unnecessary code to solve a non-problem. I personally only use +new
very rarely, and only when I know I'm only using -init
.
Since you're coming from a Java background, check out this SO question if you're curious about why Objective-C uses alloc/init instead of new like Java, C++, etc.
The problem is not with new, it is with addObject, which is a void returning method.
Your code:
[[ClassA new] addObject:[[ClassA new] addObject:[ClassA new]]];
would more be equivalent to this Java code:
ClassA = new ClassA()->AddObject( new ClassA()->AddObject( new ClassA() ) );
which would fail for the same reason, that AddObject retuns void, not self.
On top of that, the code would clearly fail since new is an "ownership" method, which means you take ownership of the created object according to the memory management rules, and yet you pass it to addObject and then forget about it, so no one is left to release it. And further you don't even save a reference to the final object.
Appropriate code would be something more like:
ClassA* c2 = [ClassA classA];
[c2 addObject:[ClassA classA]];
ClassA* c = [ClassA classA];
[c addObject:c2];
where ClassA's classA method is implemented as:
(ClassA*) classA
{
return [[ClassA new] autorelease];
}
Alternatively, you could add a further method:
(ClassA*) classAWithObject: (ClassA*) inObject
{
ClassA* c = [ClassA classA];
[c addObject:inObject];
return c;
}
and then write:
ClassA* c = [ClassA classAWithObject:[ClassA classAWithObject:[ClassA classA]]];
which would be both very true to the Cocoa/Objective C way of doing it, and equivalent to your Java code, and actually obey the memory management rules.