私はこれをしたい:
[[ClassA new] addObject:[[ClassA new] addObject:[ClassA new]]];
しかし、コンパイラは次を返します。
"error: invalid use of void expression"
それを行う方法はありますか?Javaのように:
ClassA = new ClassA( new ClassA( new ClassA()));
私はこれをしたい:
[[ClassA new] addObject:[[ClassA new] addObject:[ClassA new]]];
しかし、コンパイラは次を返します。
"error: invalid use of void expression"
それを行う方法はありますか?Javaのように:
ClassA = new ClassA( new ClassA( new ClassA()));
問題は new ではなく、void を返すメソッドである addObject にあります。
あなたのコード:
[[ClassA new] addObject:[[ClassA new] addObject:[ClassA new]]];
次の Java コードと同等です。
ClassA = new ClassA()->AddObject( new ClassA()->AddObject( new ClassA() ) );
これは、AddObject が self ではなく void を返すという同じ理由で失敗します。
その上、 new は「所有権」メソッドであるため、コードは明らかに失敗します。つまり、メモリ管理ルールに従って作成されたオブジェクトの所有権を取得し、それを addObject に渡してから忘れるので、 1つはそれを解放するために残されています。さらに、最終オブジェクトへの参照も保存しません。
適切なコードは次のようになります。
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 コードと同等であり、実際にメモリ管理規則に従います。
コード スニペットはnew
、ClassA で定義されたメソッドがインスタンス メソッドではなくクラス メソッドであり、ClassA が目的の動作を行うaddObject:
セレクターも実装していることを前提としてのみ機能します。メソッドがどのように定義されているかはわかりませんが、これが機能するには、ClassA で次のメソッド定義が必要です。
+ (ClassA *)new;
- (ClassA *)objectByAddingObject:(ClassA *)newObject;
セレクターは新しい ClassA オブジェクトへのnew
ポインターを返す必要があるため、その実装にはおそらく次のようなものが含まれます。
return [[ClassA alloc] init];
また、addObject:
セレクターは ClassA オブジェクトを別の ClassA 内に格納し、サブオブジェクトが追加された新しいオブジェクトを返す必要があります。
self.object = newObject;
return self;
へのネストされた呼び出しのためaddObject:
、そのメソッドは通常の場合のように (void) ではなく (ClassA *) を返す必要があることに注意してください。次のようなものになるように、リファクタリングを検討することをお勧めします。
[[ClassA alloc] initWithObject:[[ClassA alloc] initWithObject:[[ClassA alloc] init]]];
Objective 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]];
編集:new
から継承されているため、以下は不要NSObject
です。詳細については、クイン・テイラーの回答を参照してください。そこにいる間に、正しいことを支持してください。:)
@interface ClassA
{
//...
}
+(ClassA)new;
//...
@end
@implementation ClassA
+(ClassA)new { return [[ClassA alloc] init]; }
//...
@end