1

我提出这个是因为与 isEquals: 比较相同的对象不一定相同。一些(许多)对象仅比较某些属性以确定相等性。

这使得以下 NSSet 方法的确切行为很重要:

setByAddingObject:
setByAddingObjectsFromArray:
setByAddingObjectsFromSet:

文档没有指定当接收器和参数包含等效对象时会发生什么。生成的 NSSet 将包含来自接收者的对象,还是来自“其他”参数的对象?

请注意,在 NSMutableSet 中,它确实指定了其添加方法的行为——如果集合中已经存在“相等”对象,则不会添加对象。

4

2 回答 2

1

NSMutableSetaddObject:方法的文档用于涵盖类似的情况:

如果anObject集合中已经存在,则此方法对集合或anObject.

但是,正如您从链接中看到的那样,当前版本甚至没有这样说。甚至该声明实际上也仅涵盖尝试添加相同的对象;它没有专门解决添加不同但相等的对象。

依赖观察到但未记录的行为是危险的,不仅因为它可以在操作系统版本之间发生变化,还因为它可以在同一个过程中发生变化。那是因为 NSSet 是一个类 cluster,这意味着可能有多个实现。你得到哪一个取决于你如何创建集合;无法确保选择甚至存在特定的实现。*

那是因为它不应该重要。每个集群子类都呈现与集群接口和文档中定义的相同行为。(如果它没有,那是一个错误,你应该报告它。)鉴于所有子类都有效地做同样的事情,你得到哪个实例并不重要。

同样的原则也适用于您的对象。他们是平等的!出于这个原因,哪一个在集合中并不重要。如果它确实重要,那么它们并不是真正相等的,您需要使对象对相等的定义更加严格。(不要忘记同时更新isEqual: hash。)

根据您使用该集合的目的,您可能希望更进一步,并确保不存在两个相等的对象。为此,请将集合的所有权、维护和使用转移到成员对象的类中,并让它始终返回匹配的对象,而不是尽可能适当地创建新对象。

*即使您可以选择其中一种实现方式,也不能保证它会一直保持您所观察到的行为——它可能(墨菲说可能会)在另一个操作系统版本中有所不同。

于 2011-03-04T04:29:09.470 回答
-1

我用下面的代码对此进行了测试。SomeClass 的定义使得 propertyA 是 hash 和 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 回答