Breve domanda: perché Java consente di sovrascrivere equals()
, perché non è definitivo?
Sto leggendo la seconda edizione di Java efficace di Joshua Bloch. Sono un po 'sconcertato dalla conclusione che
There is no way to extend an instantiable class and add a value component while preserving the equals contract
Non sta dicendo lo stesso che equals()
dovrebbe essere un metodo final
?
Il libro fornisce un esempio di una classe A
con equals()
metodo e poi una classe AX
estendendo A
con il proprio metodo equals()
che è diverso dal metodo equals()
in A
.
Non entrerò nei dettagli di equals()
in A
e equals()
in AX
, ma è sufficiente dire che sono diversi . Pertanto abbiamo un problema di interoperabilità che garantisce la violazione della transitività e / o della simmetria (forse anche qualcos'altro) di equals()
quando mischiamo diverse implementazioni di A
in alcuni contesti (specialmente HashSet
, HashMap
type).
Pensando ulteriormente, non credo di essere d'accordo con la conclusione che avere qualcosa di simile
public boolean equals(Object o) {
if (o == null || o.getClass() != getClass())
return false;
...
}
è sbagliato. Penso che questo sia esattamente il modo corretto per gestire l'override di equals()
.
Java lo rende possibile, quindi Java consente di sovrascrivere equals()
per un motivo. Se avesse preso in considerazione il principio di sostituzione di Liskov in senso stretto, allora non avrebbe permesso di sovrascrivere equals()
e implicitamente rende qualsiasi implementazione di equals()
finale a livello di compilatore. Quali sono i tuoi pensieri?
Posso pensare a un caso in cui la composizione non è semplicemente adatta e sovrascrivere equals()
è l'opzione migliore. Questo è il caso in cui la classe A
deve essere resa persistente in un database e il contesto implica che non esiste alcuna raccolta con un'implementazione di A
e sottoclassi di A
come AX
.