IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

avec Java Discussion :

Quelle est la différence entre identité d'objets et égalité d'objet?


Sujet :

avec Java

  1. #1
    Membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Novembre 2015
    Messages
    156
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Novembre 2015
    Messages : 156
    Points : 52
    Points
    52
    Par défaut Quelle est la différence entre identité d'objets et égalité d'objet?
    Bonsoir!

    Je suis toujours en plein apprentissage du langage Java et j'essaye aujourd'hui de comprendre les différents types d'égalité et leur implémentation dans un code.
    Je pense avoir compris comment on réalise un méthode equals, mais d'un point de vue plus abstrait, quelle est la différence entre identité d'objets et égalité d'objet?

    Si on modélise le jeu de Dominos à l’aide de l’entité Domino qui désigne une pièce d’un jeu de dominos et de l’entité Game qui représente une partie de dominos.
    Qu serait la sémantique d'égalité sur Domino et sur Game? (je dirais à priori égalité d'objets sur game et identité sur domino mais peut-être que je me trompe...)

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
     
    //////////////////////////////   GAME   /////////////////////
     
    package tdr.td_dominos.question123;
     
    import java.util.*;
     
    public class Game implements GameAbility{
    	private List game; 
    	public Game(Domino d){
    		setGame( new LinkedList());
    	      getGame().add(d);
    	      }   
    	private void setGame(List list){
    		game=list;
    		}   
    	private List getGame(){
    		return game;
    		}
     
    	// Seule methode publique appartenant a l'interface
    	public boolean add(Domino d){
    		boolean result= addLast(d);
    		if (!result){result= addFirst(d);}
    		return result;
    		}
    	private boolean isEmpty(){
    		return getGame().isEmpty();
    		}
    	private Domino getFirst(){
    	      return (Domino) getGame().get(0);
    	      }
    	private Domino getLast(){
    	      return (Domino)  getGame().get(game.size()-1);
    	      }
    	private boolean addFirst(Domino d){
    		Domino first = getFirst();
    		boolean result= first.matchLeft(d);   
    		// first peut se mettre a droite de d: d first ou retourne(d) first
    		if (result) {
    			( (LinkedList)getGame()).addFirst(d);
    			} else{
    				System.out.println(" AJOUT IMPOSSIBLE A GAUCHE DANS LE JEU  avec " + d);}
    		return result;
    		}
    	    // Ajoute d en fin de jeu
    	    // d peut se mettre ‡ droite du last: last d ou last retourne d   
    	private boolean addLast(Domino d){
    		Domino last = getLast();
    		boolean result= last.matchRight(d); 
    		// first peut se mettre ‡ droite de d: d first ou retourne(d) first
    		if (result) {
    			( (LinkedList)getGame()).addLast(d);
    	     } else {
    	    	 System.out.println(" AJOUT IMPOSSIBLE A DROITE DANS LE JEU avec  "+ d);}
    	     return result;
    	     }
     
    	public boolean equals(Object object){
    		if (object instanceof Game){
    			return equals((Game)object);
    			}
    	     return false;
    	     }
     
    	private boolean equals(Game object){
    		return getGame().equals(object.game);
    		}
    	public void clear(){
    		getGame().clear();
    		}
     
    	public String toString(){
    		return getGame().toString();
    		}
    	}
     
    interface GameAbility{
        boolean add(Domino d);
    	}
    ////////////////////////    DOMINO  ///////////////////////
    package tdr.td_dominos.question123;
     
    public class Domino {
        private int right;
        private int left;
     
        //create a domino
        public Domino(int left,int right){
        	  setLeft(left);
        	  setRight (right);
        	  }
        //by default
        public Domino(){
        	  this(0,0);
        	  }
        //ne devrait pas Ítre public
        private int getRight(){
        	  return right;
        	  }
        private int getLeft(){
        	  return left;
        	  }
        //ne devrait pas Ítre public
        private void setRight(int value){
        	  this.right=value;
        	  }
        private void setLeft(int value){
            this.left=value;
            }
     
        public String toString (){
        	  return ("["+getLeft()+";"+getRight()+"] ");
        	  }
     
        //return true if the domino may be placed straight or by turning over at the left side
        // otherwise, return false
        // d this  or turnOver(d) this
        public boolean matchLeft(Domino d){
        	  boolean result= turnAfter(d);
        	  if (result){
        		d.rotate();
        		return result;
        		}
        	result=isAfter(d);
        	return result;
        	}
        // d va-t-il a droite du jeu? on regarde si les parties dr. de d et du jeu sont =, si oui on retorne
        // sinon on examine s'il va sans retournement (this est le domino a la droite du jeu)
        public boolean matchRight(Domino d){
        	  boolean result= turnBefore(d);
        	  if (result){
        		d.rotate();
        		return result;
        		}
            result=isBefore(d);
        	  return result;
        	  }
     
        private void rotate(){
        	  int temp=getLeft();
            setLeft(getRight());
            setRight (temp);
            }
        // d peut-il être placé à la droite de this ?
        private boolean isBefore(Domino d){
        	  return this.getRight()==d.getLeft();
        	  }
        // d peut-il être placé à la droite de this après retournement ?
        private boolean turnBefore(Domino d){
        	  return this.getRight()==d.getRight();
        	  }
        private boolean isAfter(Domino d){
            return this.getLeft()==d.getRight();
        	  }
        private boolean turnAfter(Domino d){
        	  return this.getLeft()==d.getLeft();
        	  }
     
        public boolean equals(Object object){
            if (object instanceof Domino){
                 return equals((Domino)object);
                 }
            return false;
            }
     
        private boolean equals(Domino object){
            return   turnBefore(object)&&turnAfter(object)||isBefore(object)&&isAfter(object);
            }
    }
     
     
    ////////////////    DominoTest  ///////////////////
    package tdr.td_dominos.question123;
    import java.util.*;
    /*
    game = [[2;3] , [3;4] ]
     AJOUT IMPOSSIBLE A DROITE DANS LE JEU avec  [3;5] 
     AJOUT IMPOSSIBLE A GAUCHE DANS LE JEU  avec [3;5] 
    game = [[2;3] , [3;4] ]
     AJOUT IMPOSSIBLE A DROITE DANS LE JEU avec  [2;6] 
    game must be [[6,2] , [2;3] , [3;4]]  :: [[6;2] , [2;3] , [3;4] ]
    game must be [[6,2] , [2;3] , [3;4] , [4;5]]  :: [[6;2] , [2;3] , [3;4] , [4;5] ]
    d23.equals(d34) must be false :: false
    d34.equals(new Domino(3,4)) must be true :: true
    d34.equals(new Domino(4,3)) must be true :: true
     AJOUT IMPOSSIBLE A DROITE DANS LE JEU avec  [6;2] 
    game2 = [[6;2] , [2;3] ]
    game3 = [[6;2] , [2;3] ]
    game2.equals(game3) must be true :: true
    */
     
    public class DominoTest {
     
        public static void main(String[] args){
    	//construction du jeu, melange, distribution
            Domino d23=new Domino(2,3);
            Domino d34=new Domino(3,4);
            Domino d35=new Domino(3,5);
            Domino d37=new Domino(3,7);
            Domino d26=new Domino(2,6);
     
            GameAbility game= new Game(d23);
            //game.add(d23);
            game.add(d34);
            System.out.println("game = " + game);
            game.add(d35);
            System.out.println("game = " + game);
            //System.out.println("Test = : " + game.equals(game));
            //System.out.println("Test = dom " + d23.equals(d));
            //System.out.println("game must be [[2;3]] :: "+game);
            game.add(d26);
            System.out.println("game must be [[6,2] , [2;3] , [3;4]]  :: "+game);
            Domino d54=new Domino(5,4);
            game.add(d54);
            System.out.println("game must be [[6,2] , [2;3] , [3;4] , [4;5]]  :: "+game);
            // Test égalité    
            System.out.println("d23.equals(d34) must be false :: " + d23.equals(d34));
            System.out.println("d34.equals(new Domino(3,4)) must be true :: "+ d34.equals(new Domino(3,4)));
            System.out.println("d34.equals(new Domino(4,3)) must be true :: "+ d34.equals(new Domino(4,3)));
            GameAbility game2 = new Game(d26);
            game2.add(d23);
            GameAbility game3 = new Game(d23);
            game3.add(d26);
            System.out.println("game2 = " + game2);
            System.out.println("game3 = " + game3);
            System.out.println("game2.equals(game3) must be true :: "+ game2.equals(game3));
        }
    }

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    Ce n'est pas 2 objets qui peuvent être identique, mais 2 variables : 2 variables sont identiques si elles référencent la même instance d'objet en mémoire. On teste si 2 variables sont identiques par l'opérateur == : on teste par cet opérateur si les deux variables contiennent la même référence (sorte d'identifiant si tu préfères) vers la même et unique instance d'objet en mémoire. Par ailleurs, on peut également tester l'identité de valeurs de type primitifs (int, long, double, boolean...).

    L'égalité est testée par la méthode equals(). Un objet A est considéré égal à un objet B, si A.equals(B) est vrai. Le corollaire est que B.equals(A) doit être également vrai. L'implémentation doit être faite pour respecter ça.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    public class Exemple {
     
        prviate final int valeur;
     
        public Exemple(int valeur) {
            this.valeur=valeur;
        }
     
        // on considère que les 2 objets sont égaux si leur attribut valeur sont idnetiques
        public boolean equals(Object object) {
            if ( object!=null && Exemple.class.equals(object.getClass()) ) {
                 return ((Exemple)object).valeur==valeur; // teste d'identité de valeurs de type primitif
            }
            return false;
        }
     
        // par contrat (javadoc), 2 objets égaux par equals() doivent avoir le même hashCode
        public int hashCode() {
            return valeur; // bien le même hashCode pour 2 objets Exemple égaux
        }
     
        public static void main(String[] args) {
     
             Exemple exemple1 = new Exemple(42);
             Exemple exemple2 = new Exemple(0);
             Exemple exemple3 = exemple1;
             Exemple exemple4 = new Exemple(42);
     
             System.out.println("exemple1 et exemple2 ne sont pas égaux : "+ exemple1.equals(exemple2)); // affiche false
             System.out.println("exemple1 et exemple3 sont identique : "+ (exemple1==exemple3)); // affiche true
             System.out.println("exemple1 et exemple4 sont égaux : "+ exemple1.equals(exemple4)); // affiche true
             System.out.println("exemple1 et exemple4 ne sont pas identiques : "+ (exemple1==exemple4)); // affiche false
     
        }
     
    }
    PS : Note qu'il peut être dangereux d'implémenter equals() par quelque chose comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        public boolean equals(Object object) {
            if ( object instanceof Exemple ) {
                 return ((Exemple)object).valeur==valeur; // teste d'identité de valeurs de type primitif
            }
            return false;
        }
    Parce que si on étend l'objet Exemple, l'égalité sera héritée. Exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    public class Rectangle {
        private final int hauteur;
        private final int largeur;
        public Rectangle(int largeur, int hauteur) {
           this.hauteur=hauteur;
           this.largeur=largeur;
        } 
     
        public boolean equals(Object object) {
           if ( object instanceof Rectangle ) {
              return equals((Rectangle)object);
           }
          return false;
        }
     
        protected boolean equals(Rectangle rectangle) {
             return rectangle.hauteur==hauteur && rectangle.largeur==largeur;
        }
     
       /*...*/
     
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public class Parallelepipede extends Rectangle {
     
        private final int epaisseur;
     
        public Parallelepipede(int largeur, int hauteur, int epaisseur) {
          super(largeur, hauteur);
          this.epaisseur=epaisseur;
        }
     
    }
    Si on fait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Parallelepipede p1=new Parallelepipede(10,10,10);
    Parallelepipede p2 = new Parallelepipede(10,10,20);
    p1.equals(p2) est vrai alors que sémantiquement c'est faux, par rapport à la définition d'un parallélépipède. Avec un test d'égalité sur la classe dans Rectangle, on aurait false implicitement. Il vaut mieux que 2 instances différentes soient non égales par défaut (implicitement) que vrai : on a un bug, mais pas de fonctionnement illogique (pas forcément évident à détecter).
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Membre chevronné
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 75
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Points : 1 855
    Points
    1 855
    Par défaut
    pour une fois pas d'acc avec joel Drigo.
    Comme toujours il faut savoir ce que l'on fait et effectivement on crée parfois des trucs bizarres et illogiques.
    MAIS il peut être tout aussi dangereux de baser equals sur l'égalité entre classe (au lieu de instanceof).
    Il y a plusieurs raisons pour celà mais la principale est que tu bloques ainsi tout mécanisme d'objet mandataire.
    Donc perso je commence avec instanceOf (tout en surveillant les choses mais il n'est pas interdit d'avoir des sous-classes ou des objets délégués
    que l'on peut considérer comme donnant une égalité et d'ailleurs il est surprenant de découvrir le nombre de cas où ça peut s'appliquer).
    un développement ici: http://www.demos.fr/chaines-thematiq...%20Egalite.pdf
    J'ai des principes: je peux toujours trouver une bonne raison pour les contredire .... mais j'ai des principes!
    (mon excellent bouquin sur Java : https://eska-publishing.com/fr/livre...822407076.html)

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par professeur shadoko Voir le message
    Il y a plusieurs raisons pour celà mais la principale est que tu bloques ainsi tout mécanisme d'objet mandataire.
    Avec instanceof, on ouvre la possiblité de ne pas respecter les règles de symétrie et de transitivité.
    Par ailleurs, on peut déléguer la condtion d'égalité à une méthode protected, qui peut donc être appelée par une classe d'extension : on sait ce qu'on fait, et on ne bloque pas celui qui veut absolument ne pas respecter la symétrie ou la transitivité, tout en limitant les dégats pour ceux qui ne savent pas ce qu'ils font.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  5. #5
    Membre du Club
    Homme Profil pro
    Etudiant
    Inscrit en
    Novembre 2015
    Messages
    156
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Etudiant

    Informations forums :
    Inscription : Novembre 2015
    Messages : 156
    Points : 52
    Points
    52
    Par défaut
    Merci pour vos réponses, ça m'a bien servi pour les examens!

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 12
    Dernier message: 01/06/2010, 16h57
  2. Réponses: 11
    Dernier message: 02/09/2006, 01h38
  3. Réponses: 5
    Dernier message: 03/05/2005, 18h22
  4. Réponses: 11
    Dernier message: 31/01/2005, 17h48
  5. Quelle est la différence entre le float et le real ?
    Par Manson dans le forum Débuter
    Réponses: 3
    Dernier message: 10/08/2004, 17h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo