Java .equals () instanceof sous-classe? Pourquoi ne pas appeler la super-classe égale au lieu de la rendre définitive?
Il est indiqué dans l'Objet du .equals(Object)
javadoc:
Elle est symétrique: pour toute valeur non nulle de référence les valeurs de x et y,
x.equals(y) doit retourner true si et seulement si o.est égal à(x) renvoie
vrai.
Presque partout dans l'exemple de code je vois substituée .equals(Object)
méthode qui utilise instanceof
comme l'un des premiers tests, par exemple ici: Les problèmes ou les pièges doivent être considérés lors de la substitution equals et hashCode?
public class Person {
private String name;
private int age;
public boolean equals(Object obj) {
if (obj == null)
return false;
if (obj == this)
return true;
if (!(obj instanceof Person))
return false;
...
}
}
Maintenant avec class SpecialPerson extends Person
avoir dans equals
:
if (!(obj instanceof SpecialPerson))
return false;
nous con garantit pas que .equals()
est symétrique.
Il a été discuté par exemple ici: tout-raison-de-préférez-getclass-sur-instanceof-quand-génération-est égal à
Person a = new Person(), b = new SpecialPerson();
a.equals(b); //sometimes true, since b instanceof Person
b.equals(a); //always false
Je devrais peut-être ajouter dans le début de SpecialPerson est égale appel direct à super?
public boolean equals(Object obj) {
if( !obj instanceof SpecialPerson )
return super.equals(obj);
...
/* more equality tests here */
}
source d'informationauteur user2622016
Vous devez vous connecter pour publier un commentaire.
Beaucoup d'utiliser les exemples de
instanceof
pour deux raisons: a) elle plie le nul de la vérification et de contrôle de type dans l'un ou b) l'exemple est pour le mettre en veille prolongée ou d'autres codes de réécriture de cadre.Le "correct" (conformément à la JavaDoc) la solution est d'utiliser
this.getClass() == obj.getClass()
. Cela fonctionne pour Java, car les classes sont des singletons et les VM ne le garantit. Si vous êtes paranoïaque, vous pouvez utiliserthis.getClass().equals(obj.getClass())
mais les deux sont vraiment équivalent.Cela fonctionne la plupart du temps. Mais parfois, Java cadres nécessité de ne "intelligents" les choses avec le code octet. Cela signifie généralement qu'ils créer un sous-type automatiquement. Depuis le sous-type doit être considérée comme égale à l'original type,
equals()
doit être mis en œuvre dans le "mauvais" sens, mais ce n'est pas grave car au moment de l'exécution, les sous-types seront tous de suivre certaines tendances. Par exemple, ils vont faire d'autres choses avant un setter est appelé. Cela n'a aucun effet sur le "equalness".Comme vous l'avez remarqué, les choses commencent à mal tourner quand vous avez les deux cas: Vous avez vraiment étendre les types de base et vous le mélanger avec automatique de génération de sous-type. Si vous le faites, vous devez vous assurer que vous n'utilisez jamais de types de feuilles.
Il vous manque quelque chose ici. Je vais essayer de mettre en lumière cette:
Supposons que vous avez
Person person = new Person()
etPerson personSpecial = new SpecialPerson()
alors je suis sûr que vous ne souhaitez pas que ces deux objets soient égaux. Donc, c'est vraiment de travail, comme l'exige l'égalité doit retourner false.De plus, la symétrie indique que le
equals()
la méthode dans les classes doit obéir à la même heure. Si l'un est égal à retourner true et d'autres return false, alors je dirais que la paille est dans l'est égal primordial.Votre tentative de résoudre le problème n'est pas correct. Supposons que vous avez 2 subclasss
SpecialPerson
etBizarrePerson
. Avec cette mise en œuvre,BizarrePerson
instances pourrait être égal àSpecialPerson
instances. En général, vous ne voulez pas que.ne pas utiliser
instanceof
. utilisationthis.getClass() == obj.getClass()
à la place. alors vous êtes à la vérification de cette même classe.lorsque l'on travaille avec
equals
vous devriez toujours utiliser lahashCode
et remplacer le trop!la méthode hashCode pour Personne pourrait ressembler à ceci:
et de l'utiliser comme ceci dans votre méthode equals:
Un type ne devrait pas envisager de lui-même égal à un objet de n'importe quel autre type, et même un sous-type--à moins que les deux objets dérivent d'une classe commune dont le contrat spécifie comment les descendants de différents types devraient vérifier l'égalité.
Par exemple, une classe abstraite
StringyThing
peut encapsuler des chaînes, et de fournir des méthodes pour faire des choses comme convertir une chaîne de caractères ou d'extraire des sous-chaînes, mais de ne pas imposer des exigences sur la sauvegarde de format. Une possible sous-type deStringyThing
par exemple, peut contenir un tableau deStringyThing
et encapsuler la valeur de la concaténation de toutes ces chaînes. Deux instances deStringyThing
serait défini comme égales si la conversion de chaîne à des résultats identiques, et la comparaison entre les deux, d'ailleurs impossible à distinguerStringyThing
instances dont les types ne savait rien au sujet de chaque d'autres peut-être tomber sur ce retour, maisStringyThing
-types dérivés pourraient inclure le code à optimiser les différents cas. Par exemple, si l'onStringyThing
représente "M
répétitions de caractèrech
" et une autre " représente "N
répétitions de la chaîne de Saint", et le second type sait à propos de la première, il pourrait vérifier siSt
contient rien, maisM/N
répétitions du caractèrech
. Un tel contrôle serait d'indiquer si les chaînes sont égales, sans avoir à "élargir" l'un d'eux.