Como você substitui corretamente isEqual:no Objective-C? A "captura" parece ser que, se dois objetos forem iguais (conforme determinado pelo isEqual:método), eles deverão ter o mesmo valor de hash.
A seção Introspecção do Guia de fundamentos do cacau tem um exemplo de como substituir isEqual:, copiado da seguinte forma, para uma classe chamada 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;
}
Ele verifica a igualdade do ponteiro, depois a igualdade de classe e, finalmente, compara os objetos usando isEqualToWidget:, que apenas verifica as propriedades namee data. O que o exemplo não mostra é como substituir hash.
Vamos supor que existem outras propriedades que não afetam a igualdade, digamos age. O hashmétodo não deve ser substituído de maneira que apenas namee dataafete o hash? E se sim, como você faria isso? Basta adicionar os hashes de namee data? Por exemplo:
- (NSUInteger)hash {
NSUInteger hash = 0;
hash += [[self name] hash];
hash += [[self data] hash];
return hash;
}
Isso é suficiente? Existe uma técnica melhor? E se você tiver primitivos, como int? Converta-os para NSNumberobter seu hash? Ou estruturas como NSRect?
( Peido do cérebro : originalmente escrevia "OR bit a bit" junto com |=.
if (![other isKindOfClass:[self class]])- Tecnicamente, isso significa que a igualdade não será comutativa. Ou seja, A = B não significa B = A (por exemplo, se uma é uma subclasse da outra)