On sait que les propriétés que equals () devrait satisfaire ne peuvent pas être satisfaites en implémentant simplement la méthode equals () d'une classe qui a une relation d'héritage comme indiqué ci-dessous [(Supplément 1)](#Supplement 1). .. [* 1 Référence](# 1) La solution de contournement est également décrite dans la même référence [(Supplément 2)](# Supplément 2), mais la solution d'un autre document [* 2 Reference](# 2) est décrite.
Créez une méthode statique equals () à deux arguments comme indiqué ci-dessous et appelez Object.equals () par son intermédiaire. La partie importante est la partie qui appelle equals () des deux classes. Cela peut être utilisé en dehors de cette structure de classe. Texte intégral À propos, il y a Objects.equals (Object, Object) dans l'API standard, mais seul equals () sur le côté gauche est appelé.
ObjectUtil.java
final class ObjectUtil {
private ObjectUtil() { throw new AssertionError("Not intended to be instanciated"); }
public static boolean equals(final Object lhs, final Object rhs) {
//Idem si les destinations de référence sur les côtés gauche et droit sont les mêmes
if (lhs == rhs) return true;
//Idem si les références gauche et droite sont nulles
if (lhs == null && rhs == null) return true;
//Ce n'est pas la même chose si la destination de référence sur le côté gauche ou la destination de référence sur le côté droit est nulle
if (lhs == null || rhs == null) return false;
//Si les destinations de référence sur les côtés gauche et droit sont de la même classe, égale à cette classe()Rendre
if (lhs.getClass() == rhs.getClass()) return lhs.equals(rhs);
//Si les références sur les côtés gauche et droit sont des classes différentes, les égales des deux classes()Et revenir
return lhs.equals(rhs) && rhs.equals(lhs);
}
}
// 1.La symétrie ne peut pas être satisfaite
// ->Si vous permutez les côtés droit et gauche, le résultat sera différent.
//Exemple utilisant la structure de classe ci-dessus
Point1D p1 = new Point1D(0);
Point2D p2 = new Point2D(0, 0);
assert(p1.equals(p2) == true); //Vrai car seules les valeurs x sont comparées
assert(p2.equals(p1) == false); //False pour déterminer qu'il s'agit d'une instance Point2D
// 2.La transparence ne peut être satisfaite
// -> p1 == p2 && p2 ==Même pour p3, p1==Ne devient pas p3
//Exemple utilisant la structure de classe ci-dessus
//supposition: Point2D.equals()Ajoutez ce qui suit aux spécifications
//Vrai même si l'argument est Point1D ou sa sous-classe et que la valeur x est la même
Point2D p1 = new Point2D(0, 0);
Point1D p2 = new Point1D(0);
Point2D p3 = new Point2D(0, 1);
assert(p1.equals(p2) == true); //Vrai en raison de nouvelles spécifications
assert(p2.equals(p3) == true); //true car les valeurs x ne sont pas comparées
assert(p1.equals(p3) == false); // x,false pour comparer les valeurs y
// 3.Le principe de remplacement de Riskov ne peut pas être respecté
// ->Un comportement similaire est attendu dans les sous-classes, mais pas
//Exemple utilisant la structure de classe ci-dessus
//Hypothèse 1: Point1D.equals()Modifiez les spécifications comme suit
//Vrai uniquement si l'argument est Point1D et que la valeur x est la même
//Hypothèse 2: CountingPoint1D.equals()Modifiez les spécifications comme suit
//Vrai uniquement si l'argument est CountingPoint1D et que la valeur x est la même
Point1D p1 = new Point(0);
CountingPoint1D cp1 = new CountingPoint(0);
CountingPoint1D cp2 = new CountingPoint(0);
List<CountingPoint1D> list = Arrays.asList(cp1);
assert(list.contains(cp2) == true); // cp1 ==vrai pour cp2
assert(list.contains(p1) == false); //Faux en raison de l'hypothèse 1
//Utiliser la composition au lieu de l'héritage
//Exemple
class Point2D {
private final Point1D p1;
private final int y;
...
@Override
public boolean equals(Object o) {
if (!(o instanceof Point2D)) return false;
Point2D rhs = (Point2D)o;
return p1.equals(rhs.p1) && y.equals(rhs.y);
}
}
*1 Joshua Brock (2014) "Effective Java 2nd Edition" Maruzen. Point 8 *2 Andrey Alexandresque (2013) "Langage de programmation D" Shosuisha. 6.8.3
Recommended Posts