¿Cómo anula correctamente isEqual:
en Objective-C? La "captura" parece ser que si dos objetos son iguales (según lo determinado por el isEqual:
método), deben tener el mismo valor hash.
La sección de Introspección de la Guía de Fundamentos de Cocoa tiene un ejemplo sobre cómo anular isEqual:
, copiado de la siguiente manera, para una clase llamada 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;
}
Comprueba la igualdad del puntero, luego la igualdad de clase, y finalmente compara los objetos usando isEqualToWidget:
, que solo comprueba las propiedades name
y data
. Lo que el ejemplo no muestra es cómo anular hash
.
Supongamos que hay otras propiedades que no afectan la igualdad, por ejemplo age
. No debería el hash
método puede anular tal que sólo name
y data
afecta el hash? Y si es así, ¿cómo harías eso? Simplemente agregue los hashes de name
y data
? Por ejemplo:
- (NSUInteger)hash {
NSUInteger hash = 0;
hash += [[self name] hash];
hash += [[self data] hash];
return hash;
}
¿Es eso suficiente? ¿Hay una mejor técnica? ¿Qué pasa si tienes primitivos, como int
? Convertirlos NSNumber
para obtener su hash? O estructuras como NSRect
?
( Pedo cerebral : Originalmente escribí "bitwise O" junto con ellos |=
. Significaba agregar).
if (![other isKindOfClass:[self class]])
- Esto técnicamente significa que la igualdad no será conmutativa. Es decir, A = B no significa B = A (por ejemplo, si una es una subclase de la otra)