Bagaimana Anda menimpa dengan benar isEqual:di Objective-C? "Tangkapan" tampaknya bahwa jika dua objek sama (seperti yang ditentukan oleh isEqual:metode), mereka harus memiliki nilai hash yang sama.
Bagian Introspeksi dari Panduan Dasar-Dasar Kakao memang memiliki contoh tentang cara menimpa isEqual:, disalin sebagai berikut, untuk kelas bernama 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;
}
Ini memeriksa kesetaraan pointer, kemudian kelas kesetaraan, dan akhirnya membandingkan objek menggunakan isEqualToWidget:, yang hanya memeriksa namedan dataproperti. Apa yang tidak ditunjukkan contoh ini adalah cara menimpa hash.
Anggaplah ada properti lain yang tidak memengaruhi kesetaraan, katakanlah age. Bukankah seharusnya hashmetode diganti sehingga hanya namedan datamempengaruhi hash? Dan jika demikian, bagaimana Anda akan melakukannya? Cukup tambahkan hash dari namedan data? Sebagai contoh:
- (NSUInteger)hash {
NSUInteger hash = 0;
hash += [[self name] hash];
hash += [[self data] hash];
return hash;
}
Apakah itu cukup? Apakah ada teknik yang lebih baik? Bagaimana jika Anda memiliki primitif, seperti int? Konversikan mereka ke NSNumberuntuk mendapatkan hash mereka? Atau struct suka NSRect?
( Brain fart : Awalnya menulis "bitwise OR" bersama dengan mereka |=. Dimaksudkan menambahkan.)
if (![other isKindOfClass:[self class]])- Ini secara teknis berarti kesetaraan tidak akan bersifat komutatif. Yaitu A = B tidak berarti B = A (misalnya jika satu adalah subkelas yang lain)