2012-04-18 19 views
13

C'è un modo per determinare se una classe è adatto come una chiave e funzionerà come ci si aspetta, per esempio io voglio usare NSIndexPath come una chiave nella NSDictionary ma non so per certo se due diverse istanze di NSIndexPath con gli stessi valori interi restituiranno sempre lo stesso valore di hash.chiave adatta per NSDictionary

risposta

9

documento IsEqual di Apple NSObject dice:

se due oggetti sono uguali, essi devono avere lo stesso valore di hash. Questo ultimo punto è particolarmente importante per se si definisce isEqual: in una sottoclasse e si intende inserire istanze di tale sottoclasse in una raccolta. Assicurati che definisca anche hash nella sottoclasse.

Guarda il seguente codice: Risultato

NSIndexPath *indexPath1 = [NSIndexPath indexPathForRow:0 inSection:0]; 

NSIndexPath *indexPath2 = [NSIndexPath indexPathForRow:0 inSection:0]; 

NSObject *obj1 = [[NSObject alloc] init]; 
NSObject *obj2 = [[NSObject alloc] init]; 

NSLog(@"NSIndexPath isEqual's Result: %d", [indexPath1 isEqual:indexPath2]); 
NSLog(@"NSObject isEqual's Result: %d", [obj1 isEqual:obj2]); 

uscita:

Risultato di NSIndexPath IsEqual: 1

Risultato di

NSObject IsEqual: 0

L'implementazione o f NSObject isEqual è che comare l'indirizzo di due oggetti, e l'implementazione hash è l'indirizzo dell'oggetto restituito.

NSIndexPath viene ereditato da NSObject, secondo risultato di uscita NSIndexPath ISEQUAL, attuazione ISEQUAL di NSIndexPath dovrebbe sostituire metodo ISEQUAL superclasse, e NSIndexPath anche sovrascrivere metodo hash superclasse.

In attizione, NSIndexPath è inoltre conforme al protocollo NSCopying.

Quindi NSIndexPath può essere utilizzato come classe Chiave di NSDictionary.

+1

Quindi è necessario verificare se l'implementazione di NSObjects di isEqual: e l'hash sono sovrascritti e assumere sempre lo sarà, il che non è irragionevole. Potrei sollevare un bug contro Apple perché penso che l'override di una classe sia Equal: e l'hash dovrebbe essere documentato. –

+0

Sono d'accordo con te! Il documento di Apple non è abbastanza chiaro in isEqual: e il metodo hash. – xzgyb

+1

@NathanDay: Penso che dovresti sollevare un bug se c'è una classe per cui avrebbe senso avere quei metodi sovrascritti ma non lo sono. – Chuck

4

Come un oggetto si comporta come una chiave dipende da come implementa isEqual :. Questo determinerà se due chiavi entrano in collisione.

Ad esempio, i percorsi dell'indice sono uguali - e quindi si scontrano - quando i percorsi hanno lo stesso insieme di indici. Quindi due oggetti distinti che descrivono lo stesso percorso saranno visti dal dizionario come la stessa chiave ... probabilmente come vorresti che fosse.

+1

La mia comprensione è anche il valore dell'hash è importante, immagino che sia una buona ipotesi che NSIndexPath implementa Equal: e l'hash in un modo che si comporterà come ci aspettiamo.Ma è tutto qui, solo una buona ipotesi? Stavo saltando per un protocollo o documentazione che diceva che i metodi è Equal: e l'hash sono sovrascritti invece di dipendere dall'implementazione di NSObjects. –

+0

Un oggetto è uguale se il suo valore hash è uguale al valore hash dell'altro, di solito. Quindi questo rende l'hash molto importante. Per una chiave DEVE avere una classe che produca in modo affidabile lo stesso valore di hash per lo stesso valore dell'oggetto e un valore hash distinto per ogni valore che l'oggetto potrebbe essere. Quindi un modo semplice per confrontare i due valori sarebbe vedere se i loro hash corrispondono :). – borrrden

+1

Secondo la documentazione di Apple per NSDictionary, gli oggetti chiave devono anche essere conformi al protocollo NSCopying, che NSIndexPath fa. – bneely

2

ci sono tre requisiti per i tasti NSDictionary:

  1. supporto del protocollo NSCopying
  2. ragionevole metodo -hash
  3. IsEqual

NSIndexPath dovrebbe andare bene.

+0

Ma come sai, immagino che NSIndexPath dovrebbe andare bene, ma non lo so per certo. In realtà so solo che NSString è OK perché viene usato così spesso. NSNumber, NSDate, NSURL I ASSUME sono OK, NSValue Non lo so, forse questo è un bug nella documentazione. –

+0

Beh, c'è solo un modo sicuro per scoprirlo - provalo! :-) Se guardi NSIndexPath.h, vedrai che obbedisce al protocollo NSCopying. Puoi anche vedere che ha una variabile di istanza "_hash". E sappiamo che supporta isEqual, quindi per quanto posso dire dovrebbe funzionare bene. Questo è un buon posto per usare un test unitario. E, sì, la documentazione dovrebbe essere migliore. – EricS

Problemi correlati