D'abord, je suis pas demander la différence entre eux.Java Type d'arrivée equals(): instanceof vs getClass()
J'ai une idée à l'esprit et je voudrais plus le cerveau de vérifier, ce qui semble en mesure de prendre (la plupart) les avantages de l'approche utilisant à la fois.
En bref, equals()
en Java ressemble généralement à ce sujet.
public boolean equals(Object other) {
if (other == null) return false;
if (this == other) return true;
if (this and other is not of the same type) return false
// then actual equals checking
}
Le problème réside dans le « cela et d'autres n'est pas du même type » vérifier.
Un flot de gens préfèrent utiliser if (! (other instanceof MyClass))
, qui ont l'inconvénient de
- facilement conduire à la suite asymétrique. Si autre est une sous-classe de
MyClass
et a substituéeequals()
,a.equals(b)
etb.equals(a)
ne sera pas la même - Pour éviter cela, nous devons éviter la classe des enfants de surcharger
equals()
, en le déclarant finale
L'autre flux de gens préfèrent utiliser if (getClass() != other.getClass())
, qui a le défaut de
- Violant principe de substitution Liskov. Une classe enfant de
MyClass
devrait être en mesure d'utiliser à la place deMyClass
. - Par conséquent,
a.equals(b)
sera faux sia
est deMyClass
tandis queb
est d'une classe enfant deMyClass
, même les attributs internes sont identiques.
J'ai une idée à l'esprit, je veux que les gens vérifier.
Cette approche devrait
- Si une classe enfant substituée
equals()
, les résultats doivent encore être symétrique Une classe enfant pourra toujours être utilisé comme type de parent (dans l'aspect de
equals()
etequals
n'est pas redéfinie bien sûr)public class Parent { @Override public boolean equals(Object other) { if (other == null) return false; if (this == other) return true; if (!(other instanceof Parent)) return false; try { if (other.getClass().getMethod("equals", Object.class).getDeclaringClass() != Parent.class) { return other.equals(this); } } catch(Exception neverHappen){} // do actual checking } }
L'idée principale est, si this
rencontré un objet Parent
, mais cet objet de equals()
non déclarée dans Parent
(à savoir cet objet est une classe enfant, avec equals()
substituée, je vais déléguer l'invocation equals
à l'objet de classe enfant (ou peut simplement renvoyer false).
Y at-il défaut d'utiliser cette approche que j'ai oublié? (Je suppose que la perte de performance sera une préoccupation, mais je crois que l'appel de getClass().method("equals").getDeclaringClass()
devrait être assez bon marché?
Non sûr, mais si la classe enfant fait 'super.equals (..)', vous obtiendrez un stackoverflow. Ainsi, vous finirez par réécrire la classe entière 'equals (..)' dans la classe enfant, ce qui est encore pire. – Asoub
@ Asoub ah .... exactement ... Je n'ai joué que dans les cas de parent vs enfant, parent vs enfant surchargé, mais j'ai oublié d'essayer enfant surpassé vs enfant surchargé. Il s'est avéré que si je veux que les équivalents soient correctement remplacés, j'aurai besoin de méthodes séparées pour le faire correctement :( –
@Asoub m'a rappelé quelque chose d'autre: J'ai toujours l'impression qu'utiliser getClass() dans type check de equals() donnera moi les résultats symétriques pour "extended equals" dans la classe enfant, et le seul inconvénient est la violation du principe de la substitution de Liskov.pendant une seconde cependant, il souffre aussi du problème que vous avez mentionné, que super.equals() ne peut pas être utilisé, isn –