Come si sostituisce correttamente isEqual:
in Objective-C? Il "catch" sembra essere che se due oggetti sono uguali (come determinato dal isEqual:
metodo), devono avere lo stesso valore di hash.
La sezione Introspection della Cocoa Fundamentals Guide contiene un esempio su come eseguire l'override isEqual:
, copiato come segue, per una classe denominata 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;
}
Verifica l'uguaglianza del puntatore, quindi l'uguaglianza di classe e infine confronta gli oggetti utilizzando isEqualToWidget:
, che controlla solo le proprietà name
e data
. Ciò che l'esempio non mostra è come sovrascrivere hash
.
Supponiamo che ci siano altre proprietà che non influiscono sull'uguaglianza, diciamo age
. Non dovrebbe il hash
metodo di essere ignorato tale che solo name
e data
influenzano l'hash? E se sì, come lo faresti? Basta aggiungere gli hash di name
e data
? Per esempio:
- (NSUInteger)hash {
NSUInteger hash = 0;
hash += [[self name] hash];
hash += [[self data] hash];
return hash;
}
È sufficiente? Esiste una tecnica migliore? E se avessi dei primitivi, come int
? Convertirli in NSNumber
per ottenere il loro hash? O strutture come NSRect
?
( Scoreggia cerebrale : originariamente li scriveva "bit a bit OR" insieme a |=
. Significa aggiungere.)
if (![other isKindOfClass:[self class]])
- Ciò significa tecnicamente che l'uguaglianza non sarà commutativa. Vale a dire A = B non significa B = A (ad es. Se uno è una sottoclasse dell'altro)