(Java) Comment implémenter equals () pour une classe avec des éléments de valeur ajoutés par héritage

introduction

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. equals_impl.png

Conclusion

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);
    }
}

Supplément 1

// 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

Supplément 2

//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

(Java) Comment implémenter equals () pour une classe avec des éléments de valeur ajoutés par héritage
Mappage à une classe avec un objet de valeur dans How to My Batis
[Java] Résumez comment comparer avec la méthode equals
[Java] Comment rechercher des valeurs dans un tableau (ou une liste) avec la méthode contains
[Java] Comment transformer un tableau à deux dimensions avec une instruction for étendue
[Java] [Pour les débutants] Comment insérer des éléments directement dans un tableau à deux dimensions
[Java] Comment tester s'il est nul dans JUnit
Comment convertir un contrat de solidité en une classe de contrat Java
[Java] Comment obtenir des éléments HashMap par contrôle de boucle à l'aide de l'instruction Extended for
[Java] Comment obtenir une requête par communication HTTP
[Java] Comment découper une chaîne de caractères caractère par caractère
[Java] Comment rompre une ligne avec StringBuilder
Comment utiliser la classe Java
[Java] Comment implémenter le multithreading
Comment créer une image de conteneur légère pour les applications Java
Comment déplacer une autre classe avec une action de bouton d'une autre classe.
A étudié comment appeler des services avec Watson SDK pour Java
Comment créer un conteneur Java
Comment désassembler un fichier de classe Java
Comment implémenter un travail qui utilise l'API Java dans JobScheduler
Comment changer les arguments dans la méthode [Java] (pour ceux qui sont confus en passant par valeur, passant par référence, passant par référence)
Comment décompiler un fichier de classe Java
Remplacer par une valeur selon la correspondance avec une expression régulière Java
Comment utiliser les méthodes de classe [Java]
Comment vérifier le contenu de la chaîne de caractères java de longueur fixe
Comment créer un tableau Java
Comment faire un diamant révolutionnaire en utilisant Java pour déclaration wwww
Comment gérer le type auquel j'ai pensé en écrivant un programme Java pendant 2 ans
[Java] Comment utiliser la classe Math
Comment mettre en œuvre un diaporama en utilisant Slick in Rails (un par un et plusieurs par un)
[Mémo personnel] Comment interagir avec le générateur de nombres aléatoires en Java
Comment savoir quelle version Java d'un fichier de classe a été compilée
[Petite histoire Java] Surveiller lorsqu'une valeur est ajoutée à la liste
[Java] Comment accéder au début d'une chaîne spécifique à l'aide de la classe String
Comment une personne complètement inexpérimentée a étudié pour acquérir de l'argent Java par elle-même
Comment suivre quand un bucket géré par scoop change (principalement Java)
Comment créer une application avec un mécanisme de plug-in [C # et Java]
Comment créer un résumé de calendrier Java
Comment implémenter le calcul de la date en Java
Comment implémenter le filtre de Kalman par Java
[Java] Comment utiliser la classe File
Comment compiler Java avec VsCode & Ant
[Introduction à Java] Comment écrire un programme Java
Comment créer un référentiel Maven pour 2020
Comment créer un robot Discord (Java)
Comment appliquer les conventions de codage en Java
[Traitement × Java] Comment utiliser la classe
Comment implémenter TextInputLayout avec la fonction de validation
Comment utiliser la classe Java Scanner (Remarque)
[Java] Comment utiliser la classe Calendar
J'ai créé un programme qui recherche la classe cible à partir du processus surchargé avec Java
Comment sortir un pot avec la classe principale spécifiée par gradle dans IntellijIDEA
Comment déployer un système réalisé avec Java (démarrage Wicket-Spring) sur le serveur du campus
Comment tester une classe qui gère application.properties avec SpringBoot (requête: signalée)