Re: NSDictionary objectForKey and non-standard key classes
Re: NSDictionary objectForKey and non-standard key classes
- Subject: Re: NSDictionary objectForKey and non-standard key classes
- From: Chris Kane <email@hidden>
- Date: Tue, 28 Aug 2001 09:43:37 -0600
On Tuesday, August 28, 2001, at 07:00 AM, Bob Peterson wrote:
I can't get NSDictionary to work using keys from a custom class. With
NSString and NSNumber keys it works just fine. The doc for NSDictionary
says only that the key has to support isEqual: and NSCopying.
You must implement -hash as well. -hash and -isEqual: must "agree";
that is for the things which isEqual: says are equal, the hash codes
must also be equal. Whatever tortuous things you do to determine
equality, you must make sure that this invariant holds. [And from
another point of view, if you can't figure out how to make the invariant
true, then you may not be able to do a complex -isEqual: method (that
is, situation in which two objects are equal) you might have set up.]
This is discussed more in the NSObject documentation for -hash and/or
-isEqual: (I forget which). In this case, you can compute the hash of
the string value and return that, since the equality test only depends
on the string value.
This is a case, as so very often happens, of the documentation being
written by somebody looking at whatever the implementation was at the
time, and writing down what they saw, rather than really understanding
what was going on. The hash-isEqual invariant requirement would not be
obvious by looking at the source code.
It is as if the key-equality function used by NSDictionary is "==",
where keys are a match only if they are the same address. Or perhaps
this is some fallout of the opaque hash functions alluded to in the
docs but that I'm not supposed to worry about. What is my key class
missing?
The inherited implementations of -hash and -isEqual: satisfy the
invariant, and are based on reference/pointer equality. When you
overrode one and not the other you got confusing behavior. Anything
inheriting from NSObject already supports -isEqual:, though a simple
form. If the doc says you have to override -isEqual:, that's not
correct. If you want to be more sophisticated about when your custom
objects are equal, then you need to override both.
Chris Kane
Cocoa Frameworks, Apple