为什么NSSet / NSMutableSet / NSCountedSet强制不可变对象作为条目? [英] Why don't NSSet/NSMutableSet/NSCountedSet force immutable objects as entries?

查看:161
本文介绍了为什么NSSet / NSMutableSet / NSCountedSet强制不可变对象作为条目?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

NSDictionary keys is id< NSCopying>但是集合的值只是id,并且文档表明它们的值被保留。根据设置集合的基础编程主题 docs:

NSDictionary keys are id<NSCopying> but the value for a set is just id, and the docs indicate their values are retained. According to the Set Fundamentals of the Collection Programming Topics docs:


然而,您可以修改单个对象他们支持修改)。

You can, however, modify individual objects themselves (if they support modification).

如果修改对象,这可能会影响对象的哈希值,这会影响查找。我假设一个NSSet是一个快速查找?

If you modify an object, this could affect the hashvalue of the object, which would affect lookups. I assumed that an NSSet is a fast lookup?

这里有一个例子,显示如果突变对象时事情如何突变:

Here's an example that shows how things break if you mutate objects:

    NSMutableString *str = [NSMutableString stringWithString: @"AWESOME"];
    NSCountedSet *countedSet = [[NSCountedSet alloc] init];
    [countedSet addObject: str];
    [countedSet addObject: str];

    NSLog(@"%@", @([countedSet countForObject: @"AWESOME"]));

    [str appendString: @" NOT AWESOME"];
    NSLog(@"%@", @([countedSet countForObject: @"AWESOME NOT AWESOME"]));
    NSLog(@"%@", @([countedSet countForObject: @"AWESOME"]));
    NSLog(@"%@", @([countedSet countForObject: str]));

    for(NSString *s in countedSet) {
        NSLog(@"%@ - %@", str, @([countedSet countForObject: s]));
    }

    NSSet *set = [NSSet setWithArray: @[ str ]];
    NSLog(@"Set Contains string, %@", @([set containsObject: str]));
    [str appendString: @"asdf"];
    NSLog(@"Set Contains string, %@", @([set containsObject: str]));
    NSLog(@"%@", set);

并输出我的解释:

[64844:303] 2          // Count is 2
[64844:303] 0          // Count should be 2 - if it looks for the literal string
[64844:303] 0          // Count should be 0, but can't find original object either
[64844:303] 0          // Count should be 2 - asking for actual object that's in there
[64844:303] AWESOME NOT AWESOME - 0   // Should be 2 - asking for actual object that it just retrieved
[64844:303] Set Contains string, 1    // Correct, pre-mutation
[64844:303] Set Contains string, 0    // Should be true, object is in there
[65070:303] {(
    "AWESOME NOT AWESOMEasdf"   // see?  It's in there
)}

我的采取:

基于哈希值,当哈希在集合后面改变时,它不知道该做什么,并且查找被破坏。

The set likely buckets based on hash value, when the hash is changed out behind the set, it doesn't know what to do and lookups are broken. The documentation is lacking in this area.

我的问题重述:
文档说你可以突变对象,这是不直观的。
突变对象拆分集。
WTF?

My question restated: Docs say you can mutate objects, which is not intuitive. Mutating objects breaks sets. WTF?

推荐答案

文档中的行是混乱的。但是,注意下面的三段可以说:

That line from the docs is confusing. However, note that three paragraphs down it goes on to say:


如果可变对象存储在集合中,则<$ c $
对象的c> hash 方法不应该依赖于可变对象
的内部状态,或者可变对象在它们在集合中时不应该被修改。
例如,一个可变字典可以放在一个集合中,但是你必须
不改变它,而它在那里。 (注意,
可能很难知道给定的对象是否在集合中)。

If mutable objects are stored in a set, either the hash method of the objects shouldn’t depend on the internal state of the mutable objects or the mutable objects shouldn’t be modified while they’re in the set. For example, a mutable dictionary can be put in a set, but you must not change it while it is in there. (Note that it can be difficult to know whether or not a given object is in a collection).

代码演示是基于散列的集合类的已知属性。如果一个关键对象被实现,使得复制返回原来的,这是固有的可变的,它也可以影响字典。

What your code is demonstrating is a known property of the hash-based collection classes. It can affect dictionaries, too, if a key object is implemented such that copying returns the original, which is inherently mutable.

没有真正的方法来测试一个对象是否可变。

There's no real way to test if an object is mutable. So, it can't force immutability.

另外,如上面引用的引用,可以创建一个可变类,其 hash 和平等不受突变影响。

Also, as alluded to in the quote above, it's possible to make a mutable class whose hash and equality are not affected by mutations.

最后,如果这些集合类只能用于可复制类和复制的元素(像字典制作他们的钥匙的副本)。集合用于表示关系等等,如果您尝试在对象之间建立关系,而不是与单独的副本建立关系,那么集合将不会执行。

Finally, it would too severely limit the utility of those collection classes if they could only be used with copyable classes and made copies of the elements (like dictionaries make copies of their keys). The collections are used to represent relationships, among other things, and it wouldn't do if you tried to establish a relationship between objects but instead established a relationship to a separate copy.

这篇关于为什么NSSet / NSMutableSet / NSCountedSet强制不可变对象作为条目?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆