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 name
i 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 hash
metoda być przesłonięte tak, że tylko name
i data
wpływać na hash? A jeśli tak, to jak byś to zrobił? Po prostu dodaj skróty name
i 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 NSNumber
uzyskać 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)