• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Implementing isEqual: and hash
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Implementing isEqual: and hash


  • Subject: Re: Implementing isEqual: and hash
  • From: "Adam R. Maxwell" <email@hidden>
  • Date: Sat, 23 Aug 2008 12:05:44 -0700


On Aug 23, 2008, at 10:26 AM, Jeff Johnson wrote:

On Aug 23, 2008, at 11:38 AM, Adam R. Maxwell wrote:

On Aug 23, 2008, at 5:13 AM, Michael Ash wrote:

On Sat, Aug 23, 2008 at 7:41 AM, Graham Cox <email@hidden> wrote:
I have a class for which equality can be defined as having the same internal
string value (which happens to be a UUID-turned-string). I can easily
implement isEqual: based on that but the docs say I also need to implement
-hash. Any pointers on what is a good way to do that? Could I just safely
defer to the -hash returned by the string in question?

The implementation of -hash should *always* match the implementation of -isEqual:.

And as Jim alluded, -hash must not depend on mutable properties; if the hash changes while the object is in a hashing collection, you'll end up with random crashes.

Right. Thus, it's a bad idea to use mutable properties in isEqual:. If you find yourself tempted to do that, impement an isEqualToMyClass: method rather than isEqual:.

CF collection callbacks are also handy in cases like this, since you can use equality functions that may not be correct for the general case of isEqual:.


If you compare primitives in -isEqual:, you should combine them (using
xor or the like) in -hash. If you compare objects by calling - isEqual:
on them, you should combine their hashes (using xor or the like). If
you do some of each, combine them all.

What's the motivation for combining hashes in this case? I've wondered what is the best thing to do when isEqual: is based on comparing multiple ivars; I typically just use one of them for the hash.

It's a documented requirement of the isEqual: and hash methods that the hash must be the same when isEqual: returns YES. Thus, whatever logic that returns YES in isEqual: must have some kind of match in hash.

If I have

@interface Test : NSObject
{
  id ivar1;
  id ivar2;
}
@end

@implementation Test

- (BOOL)isEqual:(id)other
{
if ([other isKindOfClass:[self class]] == NO) return NO;
return ([ivar1 isEqual:(Test *)other->ivar1] && [ivar2 isEqual: (Test *)other->ivar2]);
}


- (unsigned)hash { return [ivar1 hash]; }

@end

I believe it's sufficient to use [ivar1 hash], since the object is only equal if ivar1 is equal in both objects. I was just curious to know what you gain by using ([ivar1 hash] ^ [ivar2 hash]); is it possible to know in general if it reduces collisions? Presumably that depends on the hash table implementation as well.

--
Adam

Attachment: smime.p7s
Description: S/MIME cryptographic signature

_______________________________________________

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

  • Follow-Ups:
    • Re: Implementing isEqual: and hash
      • From: Jeff Johnson <email@hidden>
References: 
 >Implementing isEqual: and hash (From: Graham Cox <email@hidden>)
 >Re: Implementing isEqual: and hash (From: "Michael Ash" <email@hidden>)
 >Re: Implementing isEqual: and hash (From: "Adam R. Maxwell" <email@hidden>)
 >Re: Implementing isEqual: and hash (From: Jeff Johnson <email@hidden>)

  • Prev by Date: Re: error codes
  • Next by Date: How to read pixel values of monochrome images
  • Previous by thread: Re: Implementing isEqual: and hash
  • Next by thread: Re: Implementing isEqual: and hash
  • Index(es):
    • Date
    • Thread