1

isEquals:と同じものを比較するオブジェクトは必ずしも同一ではないため、これを取り上げます。一部の(多くの)オブジェクトは、特定のプロパティのみを比較して同等性を判断します。

そのため、次のNSSetメソッドの正確な動作が重要になります。

setByAddingObject:
setByAddingObjectsFromArray:
setByAddingObjectsFromSet:

ドキュメントには、レシーバーとパラメーターに同等のオブジェクトが含まれている場合に何が起こるかは指定されていません。結果のNSSetには、レシーバーからのオブジェクト、または「その他」パラメーターからのオブジェクトが含まれますか?

NSMutableSetでは、addメソッドの動作を指定していることに注意してください。「等しい」オブジェクトがセットにすでに存在する場合、オブジェクトは追加されません。

4

2 に答える 2

1

addObject:同様のケースをカバーするために使用されるNSMutableSet のメソッドのドキュメント:

セットに がすでに存在する場合anObject、このメソッドはセットまたは のいずれにも影響しませんanObject

しかし、リンクをたどってみるとわかるように、現在のバージョンにはそのようなことさえありません。そして、そのステートメントでさえ、実際には同じオブジェクトを追加しようとしているだけです。異なるが等しいオブジェクトの追加には具体的に対処していません。

観察されているが文書化されていない動作に依存することは、OS のバージョン間で変化する可能性があるだけでなく、まったく同じプロセス内で変化する可能性があるため、危険です。これは、NSSet がクラス clusterであるためです。つまり、複数の実装が存在する可能性があります。どちらを取得するかは、セットの作成方法によって異なります。特定の実装が選択されること、または存在することを保証する方法はありません。*

それは問題にすべきではないからです。クラスター化されたサブクラスはすべて、クラスターのインターフェースとドキュメントで定義されているものと同じ動作を示します。(そうでない場合、それはバグであり、報告する必要があります。) すべてのサブクラスが事実上同じことを行うことを考えると、どのサブクラスのインスタンスを取得しても問題ありません。

オブジェクトにも同じ原則が適用されます。彼らは等しいです!そのため、どちらがセットに入っているかは問題ではありません。それが問題になる場合、それらは真に等しいとは言えず、オブジェクトの等価性の定義をより厳格にする必要があります。isEqual: ( と の両方を 更新することを忘れないでくださいhash。)

セットを何に使用しているかによっては、それをさらに進めて、2 つの同等のオブジェクトが存在しないようにしたい場合があります。これを行うには、セットの所有権、保守、および使用をメンバー オブジェクトのクラスに移動し、可能かつ適切な場合に新しいオブジェクトを作成するのではなく、常に一致するオブジェクトを返すようにします。

*また、実装の 1 つを選択できたとしても、それがあなたが観察した動作を永久に保持するという保証はありません。別の OS バージョンでは異なる可能性があり、Murphy はおそらくそうすると言います.

于 2011-03-04T04:29:09.470 に答える
-1

私はこれを次のコードでテストしました。SomeClassは、propertyAがハッシュおよびisEqualsで考慮される唯一のプロパティであるように定義されています。

SomeClass *objectA = [[[SomeClass alloc] init] autorelease];
objectA.propertyA = @"test";
objectA.propertyB = @"objectA";

SomeClass *objectB = [[[SomeClass alloc] init] autorelease];
objectB.propertyA = @"test";
objectB.propertyB = @"objectB";

NSSet *setA = [NSSet setWithObject:objectA];
NSSet *setB = [NSSet setWithObject:objectB];
NSSet *setC = [setA setByAddingObjectsFromSet:setB];

NSLog(@"Set A\n%@", [setA description]);
NSLog(@"Set B\n%@", [setB description]);
NSLog(@"Set C\n%@", [setC description]);

このコードを実行したときの出力は次のとおりです。

2011-03-03 16:35:15.041 temp[50311:207] Set A
{(
    {SomeClass propertyA:test propertyB:objectA}
)}
2011-03-03 16:35:15.041 temp[50311:207] Set B
{(
    {SomeClass propertyA:test propertyB:objectB}
)}
2011-03-03 16:35:15.042 temp[50311:207] Set C
{(
    {SomeClass propertyA:test propertyB:objectA}
)}

これは、パラメータに同等のオブジェクトが含まれている場合、新しく作成されたNSSetにRECEIVERからのオブジェクトが含まれることを示しています。

編集-目前の質問に直接答えるので、これを答えとしてマークします。しかし、私は以下のピーターの答えと彼が表明する懸念を指摘します。この動作文書化されていないため、これらのコアクラスがこの点で変更される可能性は非常に低いですが、そのリスクを指摘する価値があります。この動作を想定してコードを記述した場合、将来のリリースで破損する可能性があります。買い手責任負担。

于 2011-03-04T00:40:05.070 に答える