¿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 namey 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 hashmétodo puede anular tal que sólo namey dataafecta el hash? Y si es así, ¿cómo harías eso? Simplemente agregue los hashes de namey 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 NSNumberpara 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)