новый на цель-с - PullRequest
3 голосов
/ 24 июня 2009

Я хочу сделать это:

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

но компилятор возвращает:

"error: invalid use of void expression"

Есть ли способ сделать это? как в Java:

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

Ответы [ 5 ]

5 голосов
/ 24 июня 2009

Реальная проблема заключается в том, что -[ClassA addObject:], скорее всего, имеет тип возврата void , поэтому вы не можете вложить это выражение в качестве аргумента для внешнего -addObject: call. Например, см. Документацию для -[NSMutableArray addObject:] - подпись метода - - (void) addObject:(id)anObject. Это может застать вас врасплох, если вы привыкли к другому поведению на другом языке, особенно на Java. Также обратите внимание, что -removeObject: возвращает void, а не объект, который был удален.

Кроме того, все упускают из виду то, что +new наследуется, если не переопределено - см. +[NSObject new]. Однако использование +new не в моде, и +alloc/-init... предпочтительнее. Одна из причин заключается в том, что, поскольку +new в любом случае вызывает -init, вы должны создать вариант + new ... для соответствия каждому -init ... в классе. К этому моменту вы получите много ненужного кода для решения не проблем. Лично я использую +new очень редко, и только когда я знаю, что я использую только -init.

Поскольку вы работаете с Java-фоном, посмотрите этот вопрос SO , если вам интересно, почему Objective-C использует alloc / init вместо new, например Java, C ++ и т. Д. *

2 голосов
/ 25 июня 2009

Проблема не в 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]]];

, который был бы как очень верным для способа Какао / Objective C, и эквивалентен вашему Java-коду, и фактически подчинялся бы правилам управления памятью.

2 голосов
/ 24 июня 2009

Ваш фрагмент кода будет работать только при условии, что метод 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]]];
0 голосов
/ 24 июня 2009

edit: Следующее необязательно, поскольку new наследуется от NSObject. См. ответ Куинн Тейлор для получения подробной информации, и пока вы там, подтвердите его правильность. :)

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

@implementation ClassA
+(ClassA)new { return [[ClassA alloc] init]; }
//...
@end
0 голосов
/ 24 июня 2009

В цели C, обычно для создания и инициализации нового объекта, вы делаете что-то вроде следующего:

[[ClassA alloc] init]

alloc , выделяет память для объекта и init инициализирует его.

Я не знаю деталей 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]];
...