2

I know that I can override hash and isEqual to check 2 instances equality. Xcode has the default snippet and doucument https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/ObjectComparison.html as following

- (BOOL)isEqual:(id)other
{
    if (other == self) {
        return YES;
    } else if (![super isEqual:other]) { //WHAT is this line mean ?
        return NO;
    } else {
        return <#comparison expression#>;
    }
}

- (NSUInteger)hash
{
    return <#hash expression#>;
}

Okay,

  1. other == self check two objects' pointers.

  2. if ![super isEqual:other], what is this line means ? If super object is not equal other, return NO ? Then it will always return NO, the step 3 will not be executed.

Am I wrong ?

Thanks.

Piyush
  • 1,534
  • 12
  • 32
tsing gao
  • 148
  • 6
  • It is checking if the superclass's implementation of isEqual: is false. – Tim Apr 13 '16 at 08:45
  • if ![super isEqual:other] : as you are overriding the methods, it simply calling the base class method. – Suhas Arvind Patil Apr 13 '16 at 08:48
  • 1
    If super class is NSObject, then it checks two instances' pointers, which will return false. Then the step 3 will not be executed ? right ? – tsing gao Apr 13 '16 at 08:49
  • yeah, refer the similar implementation done here http://stackoverflow.com/questions/254281/best-practices-for-overriding-isequal-and-hash – Suhas Arvind Patil Apr 13 '16 at 08:53
  • Thanks. Usually, the super class is NSObject, If I uses the default implement and modify the hash methods and step 3, the step 3 will not be checked and the isEqual return NO, which is not my expectation. Why the Apple use a default implement like this ? Does it have other reasons ? – tsing gao Apr 13 '16 at 08:59
  • yes, they might be using this in there existing classes – Suhas Arvind Patil Apr 13 '16 at 09:00
  • I think this code just not for NSObject's ancestors. Just common patter for all class. – Cy-4AH Apr 13 '16 at 09:21

3 Answers3

4

It's a typical implementation in a class-hierarchy, that is, if your class derives from a super class that has its own meaningful isEqual: implementation. In that case it is wise to let the super class test the equality of the common properties. If the common part is not equal, then there is no chance that the derived objects are equal.

It is not needed if you derive directly from NSObject.

Actually, you'll need an extra step as well:

- (BOOL)isEqual:(id)other
{
    if (other == self) {
        return YES;
    } else if (![super isEqual:other]) {
        return NO;
    } else if (![other isKindOfClass:[MyClass class]]) {
        return NO; // comparing incompatible objects 
    } else {
        MyClass *myOther = (MyClass *) other;
        return <#compare between self and myOther#>;
    }
}
fishinear
  • 6,101
  • 3
  • 36
  • 84
0

There is a slightly different between Hash and isEqual in Objective-C. First of all, NSObject checks equality with another object with the method isEqual: and basically, two objects may be equal to another, if they share a common set of observable properties.

Hashing in object comparison is an extra step in determining collection membership, which will faster your operation.

This will explain a little bit about hash and isEqual

  • Object equality is commutative ([a isEqual:b] --> [b isEqual:a])
  • If objects are equal, then their hash values must also be equal ([a isEqual:b] --> [a hash] == [b hash])
  • However, the converse does not hold: the hash values of two objects are equal do not mean that their values to be equal.

I hope this would be helpful. For reference, you can visit this link http://nshipster.com/equality/

HSG
  • 1,224
  • 11
  • 17
  • This appears to be a summary of an [NSHipster article](http://nshipster.com/equality/#equality-&-identity). Phrases like "I hope this would be helpful" make this look like clear plagiarism. – trojanfoe Apr 13 '16 at 10:47
0

Let's look at one example of class inheritance:

@interface A : NSObject
@property (nonatomic, assign, readwrite) NSInteger fieldA;
@end 

@interface B : A
@property (nonatomic, assign, readwrite) NSInteger fieldB;
@end 

Now, if you want to implement equality on A, then you want to base it on the equality of fieldA:

// A equality
- (BOOL)isEqual:(id)other {
   ... 

   return [self fieldA] == [other fieldA];
}

When you are implementing equality on B, you need two conditions - first you have to make sure that fieldA is equal and then you have to make sure that fieldB is equal.

// B equality
- (BOOL)isEqual:(id)other {
   ... 

   return [super isEqual:other] && [self fieldB] == [other fieldB];
}

That's exactly what the [super isEqual:other] is doing - it checks the equality requirement of the superclass, that is fieldA.

To be honest, this isEqual: template is not very good. It is missing one of the most important things and that is the class equality check:

if (![other isMemberOfClass:[self class]]) {
   return NO;
}

You don't need this check only when you never mix instances of different classes. However, when you start putting instances of A and B into the same array/dictionary etc. you will have crashes when trying to compare instances of A with instances of B.

Sulthan
  • 128,090
  • 22
  • 218
  • 270