Jak poprawnie przesłonić isEqual:cel C? „Złap” wydaje się polegać na tym, że jeśli dwa obiekty są równe (jak określa isEqual:metoda), muszą mieć tę samą wartość skrótu.
Introspekcja odcinek kakao Fundamentals Przewodnik ma przykład, w jaki sposób zastąpić isEqual:, kopiowane następująco, dla klasy o nazwie 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;
}
Sprawdza równość wskaźnika, następnie równość klas, a na koniec porównuje obiekty isEqualToWidget:, które tylko sprawdzają właściwości namei data. W tym przykładzie nie pokazano, jak zastąpić hash.
Załóżmy, że istnieją inne właściwości, które nie wpływają na równość, powiedzmy age. Nie powinien hashmetoda być przesłonięte tak, że tylko namei datawpływać na hash? A jeśli tak, to jak byś to zrobił? Po prostu dodaj skróty namei data? Na przykład:
- (NSUInteger)hash {
NSUInteger hash = 0;
hash += [[self name] hash];
hash += [[self data] hash];
return hash;
}
Czy to wystarczy? Czy istnieje lepsza technika? Co jeśli masz prymitywy int? Konwertuj je, aby NSNumberuzyskać skrót? Lub struktury takie jak NSRect?
( Brain fart : Oryginalnie napisałem je „bitowe LUB” razem z nimi |=. Znacząco dodaj.)
if (![other isKindOfClass:[self class]])- Technicznie oznacza to, że równość nie będzie przemienna. Tj. A = B nie oznacza B = A (np. Jeśli jedna jest podklasą drugiej)