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 name
e 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 hash
método não deve ser substituído de maneira que apenas name
e data
afete o hash? E se sim, como você faria isso? Basta adicionar os hashes de name
e 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 NSNumber
obter 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)