/ / Tecniche per l'implementazione di hash su oggetti di cacao mutabili: obiettivo-c, cacao, cacao-tocco, hash

Tecniche per implementare -hash su oggetti mutevoli di cacao - hash obiettivo-c, cacao, cacao, hash

La documentazione per -hash dice che non deve cambiare mentre un oggetto mutabile è archiviato in una raccolta e allo stesso modo la documentazione per -isEqual: dice il -hash il valore deve essere lo stesso per oggetti uguali.

Detto questo, qualcuno ha qualche suggerimento per il modo migliore di implementare -hash tale da soddisfare entrambe queste condizioni e tuttavia viene effettivamente calcolato in modo intelligente (ovvero non ritorna 0)? Qualcuno sa come lo fanno le versioni mutabili delle classi fornite dal framework?

La cosa più semplice da fare è ovviamente dimenticarela prima condizione (che non cambia) e assicurati solo di non mutare mai accidentalmente un oggetto mentre si trova in una raccolta, ma mi chiedo se esiste una soluzione più flessibile.

MODIFICARE: Mi chiedo qui se è possibilemantenere i 2 contratti (dove oggetti uguali hanno hash uguali e gli hash non cambiano mentre l'oggetto si trova in una raccolta) quando muto lo stato interno dell'oggetto. La mia inclinazione è dire "no", a meno che non faccia qualcosa di stupido come sempre restituisco 0 per l'hash, ma è per questo che sto facendo questa domanda.

risposte:

2 per risposta № 1

Domanda interessante, ma penso a quello che vuoiè logicamente impossibile. Supponiamo che tu inizi con 2 oggetti, A e B. "Sono entrambi diversi e iniziano con codici hash diversi. Aggiungi entrambi a una tabella hash. Ora, vuoi mutare A, ma non puoi cambiare il codice hash perché è già nella tabella. Tuttavia, è possibile cambiare A in modo tale che .equals () B.

In questo caso, hai 2 scelte, nessuna delle quali funziona:

  1. Cambia l'hashcode di A in uguale a B.hashcode, il che viola il vincolo di non modificare i codici hash mentre sei in una tabella hash.
  2. Non modificare l'hashcode, nel qual caso A. equals (B) ma non hanno gli stessi hashcode.

Mi sembra che non ci sia modo di farlo senza usare una costante come hashcode.


2 per risposta № 2

La mia lettura della documentazione è che il valore di un oggetto mutabile per hash può (e probabilmente dovrebbe) cambiare quando è mutato, ma non dovrebbe cambia quando l'oggetto non è stato mutato. La parte della documentazione a cui fare riferimento, quindi, sta dicendo: "Non" mutare oggetti che sono memorizzati in una raccolta, perché ciò causerà il loro hash valore da cambiare ".

Per citare direttamente dal Documentazione di NSObject per hash:

Se un oggetto mutabile viene aggiunto a che raccoltausa i valori hash per determinare la posizione dell'oggetto in raccolta, il valore restituito da il metodo hash dell'oggetto non deve cambia mentre l'oggetto è nel collezione. Pertanto, o l'hash il metodo non deve fare affidamentosu uno dei informazioni sullo stato interno dell'oggetto o devi assicurarti che l'oggetto le informazioni sullo stato interno no cambia mentre l'oggetto è nel collezione.

(Enfasi mia.)


1 per risposta № 3

La domanda qui non è come soddisfare entrambi questi requisiti, ma piuttosto quale tu dovrebbero incontrare. Nella documentazione di Apple, si afferma chiaramente che:

un dizionario mutabile può essere inserito in una tabella hash ma non è necessario modificarlo mentre è presente.

Detto questo, sembra più importante che tusoddisfare i requisiti di uguaglianza degli hash. L'hash di un oggetto dovrebbe sempre essere un modo per verificare se un oggetto è uguale a un altro. Se questo non è mai il caso, non è una vera funzione hash.

Solo per finire la mia risposta, fornirò un esempio di una buona implementazione dell'hash. Supponiamo che tu stia scrivendo l'implementazione di -hash su una raccolta che hai creato. Questa raccolta memorizza una matrice di oggetti NSO come puntatori. Poiché tutti gli oggetti NSO implementano la funzione hash, è possibile utilizzare i loro hash nel calcolo dell'hash della raccolta:

- (NSUInteger)hash {
NSUInteger theHash = 0;
for (NSObject * aPtr in self) { // fast enumeration
theHash ^= [aPtr hash];
}
return theHash;
}

In questo modo, due oggetti di raccolta contenenti gli stessi puntatori (nello stesso ordine) avranno lo stesso hash.


0 per risposta № 4

Dato che stai già eseguendo l'override di -isEqual: per fare un confronto basato sul valore, sei sicuro di aver davvero bisogno di preoccuparti di -hash?

Non riesco a indovinare per cosa hai esattamente bisogno di questoCerto, ma se vuoi fare un confronto basato sul valore senza deviare dalla prevista implementazione di -isEqual: per restituire SÌ solo quando gli hash sono identici, un approccio migliore potrebbe essere quello di imitare NSString "s -isEqualToString :, in modo da creare il tuo -isEqualToFoo: metodo invece di utilizzare o ignorare -isEqual :.


-2 per risposta № 5

In Java, la maggior parte delle classi mutabili non ha la precedenza Object.hashCode () in modo che l'implementazione predefinita restituisca un valore basato sull'indirizzo dell'oggetto e che non cambi. Potrebbe essere lo stesso con l'Obiettivo C.