Re: Objects as keys NSMutableDictionary
Re: Objects as keys NSMutableDictionary
- Subject: Re: Objects as keys NSMutableDictionary
- From: James Bucanek <email@hidden>
- Date: Sun, 9 Jul 2006 07:17:19 -0700
Matthias Winkelmann wrote on Sunday, July 9, 2006:
>I'm having a little problem with NSMutableDictionary and would like
>to find out what "best practice" for this is.
>
>Here's a contrived example: A class "exam" should store the result
>for each student. So we have 20 students and an NSNumber for each.
>I'd like to store them like this:
>
>in init:
>NSMutableDictionary *result = [NSMutableDictionary dictionary];
>
>
>- (void)setResult:(NSNumber *)aResult forStudent:(Student *)aStudent
>{
> [results setObject:aResult forKey:aStudent];
>}
Should work just fine, with a few caveats...
>Now firstly, NSDictionary likes NSStrings as keys for key-value
>coding. I don't depend on that, so I'm willing to ignore it.
NSDictionay doesn't care. I use all kinds of objects as keys, NSNumber being very popular. What NSDictionary is doesn't like is key objects that don't follow the required contract. Specifically, the isEqual: and hash contract must be valid and hash should return something "hashy", not some constant of a value likely to be the same as other objects. This is very important for the efficiency of the dictionary. See the documentation for the contract for hash: <file:///Developer/ADC Reference Library/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/NSObject/hash>
To encode a dictionary as a property list the property list framework requires that the keys to a dictionary be strings. But that's a property list encoding requirement, not an NSDictionary requirement.
>However,
>it also requires the keys to be immutable, so I'd have to copy the
>student object. I don't want to do that, since I want to later be
>able to go back and retrieve the result for that specific student.
Technically, NSDictionary and NSSet only require that the comparison and hash behavior of the objects being used as keys be followed. NSDictionary really doesn't care if the key objects change as long as the results of [key isEqual:x], [key hash], and [key compare:x] don't change over time. Cocoa's sets (like most collection implementations) rely on the fact that the keys are stable in terms of sorting and comparison.
Taking the Student object as an example again, if you implemented -[Student compare:], -[Student isEqual:], and -[Student hash] so that they operated on a unique and immutable property of Student (like the student's ID) and ignored everything else in the Student object, then you could modify Student without changing its comparison behavior and it would be perfectly suitable for use as a key in a dictionary.
On the other hand, if the comparisons and hash methods of Student would return different values if you changed any property of the student (for example, the student's grade average), then you would not want to use them as keys. What I typically do in this situation is create a proxy object that is stable. Something like a StudentRef class that used only some immutable property of the student to perform comparisons. Then you would add and retrieve values like this:
[results setObject:aResult forKey:[[[StudentRef alloc] referenceWithStudent:aStudent] autorelease]];
...
result = [results objectForKey:[[[StudentRef alloc] referenceWithStudent:aStudent] autorelease]];
--
James Bucanek
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden