Wie überschreiben Sie isEqual:Objective-C richtig ? Der "Haken" scheint zu sein, dass zwei Objekte, wenn sie gleich sind (wie durch die isEqual:Methode bestimmt), denselben Hashwert haben müssen.
Der Abschnitt Introspection des Cocoa Fundamentals Guide enthält ein Beispiel zum Überschreiben isEqual:einer Klasse mit dem Namen MyWidget:
- (BOOL)isEqual:(id)other {
if (other == self)
return YES;
if (!other || ![other isKindOfClass:[self class]])
return NO;
return [self isEqualToWidget:other];
}
- (BOOL)isEqualToWidget:(MyWidget *)aWidget {
if (self == aWidget)
return YES;
if (![(id)[self name] isEqual:[aWidget name]])
return NO;
if (![[self data] isEqualToData:[aWidget data]])
return NO;
return YES;
}
Es prüft die Zeigergleichheit, dann die Klassengleichheit und vergleicht schließlich die Objekte mit isEqualToWidget:, wobei nur die Eigenschaften nameund überprüft datawerden. Was das Beispiel nicht zeigt, ist das Überschreiben hash.
Nehmen wir an, es gibt andere Eigenschaften, die beispielsweise die Gleichheit nicht beeinflussen age. Sollte nicht das hashVerfahren, außer Kraft gesetzt wird , dass nur nameund dataden Hash beeinflussen? Und wenn ja, wie würden Sie das machen? Fügen Sie einfach die Hashes von nameund hinzu data? Zum Beispiel:
- (NSUInteger)hash {
NSUInteger hash = 0;
hash += [[self name] hash];
hash += [[self data] hash];
return hash;
}
Ist das ausreichend Gibt es eine bessere Technik? Was ist, wenn Sie Primitive haben int? Konvertieren Sie sie in NSNumber, um ihren Hash zu bekommen? Oder Strukturen wie NSRect?
( Brain Fart : Ursprünglich schrieb "bitwise OR" sie zusammen mit |=. Gemeint hinzufügen.)
if (![other isKindOfClass:[self class]])- Dies bedeutet technisch gesehen, dass Gleichheit nicht kommutativ ist. Dh A = B bedeutet nicht B = A (z. B. wenn eine eine Unterklasse der anderen ist)