Re: When do I need to override hash?
Re: When do I need to override hash?
- Subject: Re: When do I need to override hash?
- From: Quincey Morris <email@hidden>
- Date: Thu, 20 Aug 2009 21:44:36 -0700
On Aug 20, 2009, at 20:51, Seth Willits wrote:
On Aug 20, 2009, at 2:31 PM, Alastair Houghton wrote:
The -hash method is important for objects that are used as keys in
associative collections. So the worry about the hash value
changing when an object's properties are altered is a bit of a red
herring, because you *aren't supposed to change keys in associative
collections*. If you do that in just about *any* implementation,
ObjC or otherwise, you'll get undefined behaviour.
So, in practice, it's perfectly safe in 99.9% of cases to base your
hash off your object's properties. In the specific case when
you're mutating objects that are keys in associative collections
(NSDictionary and NSSet being the primary examples, along with
their CoreFoundation counterparts), if you change a property that
affects *either* -isEqualTo: *or* -hash, you need to remove the
object before mutating it and then add it back again afterwards.
The documentation, nor did many others' comments on this topic, make
it clear that the mutability is only a problem for the *keys*.
Others and the docs talk about (paraphrasing) "putting an object
into a collection", not "using an object as a key in an associative
collection."
Yes. I believe Alastair misspoke.
What he said is actually 99.9% true, but establishes a different
point. The keys in a dictionary (or other keyed collection, like a map
table) need to be immutable objects, but that's unrelated to the hash.
Mutability in the keys would be bad, hash or no hash.
Separately, keyed collections use isEqual: on the keys to determine
equality, so they need the isEqual:/hash to follow the rules. (Because
the rules imply they can short-circuit some potentially expensive
isEqual: invocations by trying fast hash comparison first. Whether
they do that is an implementation detail we don't know.)
Separately, keyed collections may (and presumably do) use *key* hash
values to distribute object values in memory. (Presumably, the key
hashes may also be used to distribute key values in memory. That's an
implementation detail we don't know.)
Separately, collections use isEqual: on the object values to determine
equality, when they care. (I doubt that NSDictionary cares about
object value equality, but NSSet certainly does, as does NSArray, when
asked to compare objects.)
Separately, collections may (and presumably sometimes do) use *object*
hash values to distribute objects in memory. (Obviously, NSSet does,
and for all we know NSDictionary does too, to distribute object values
that stored under the same key hash value -- though it would be an
implementation detail.)
So object values must also follow the isEqual:/hash rules.
So AFAIK your reading of the documentation is absolutely correct.
Object values cannot be mutated while in a collection, unless their
hash value doesn't depend on the mutated properties. Key values cannot
be mutated while used in a collection, period.
[Actually, for all I know, key values *can* be mutated while used in a
collection, provided the hash value doesn't change, but even if it
technically feasible it sounds so un-useful I'd argue it's better just
to assert that it's not allowed.]
As far as the rest of this thread is concerned, I'd suggest we pay
attention to what Clark Cox has said and ignore everything else. Of
all our posts here today, he's the only one who's been *both* correct
*and* brief simultaneously. :)
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden