Partage
  • Partager sur Facebook
  • Partager sur Twitter

[Question] Immutabilite et copie d'objet

    30 novembre 2015 à 16:00:44

    Salut a tous,

    J'ai une question concernant les objets immutables (ou immuables en français) et leur copie.

    J'ai bien compris que deux objets A et B (B étant une copie de A) provenant d'une même classe T immutable sont bien différents en mémoire.

    Le problème que je me pose est comment s'effectue la copie ?

    Est-ce que :

    T A = new T(p1,p2);
    T B;
    
    B = A;

    Suffit a ce que B récupère les paramètres p1 et p2, et que tout action sur A n'affecte pas B (du coup oui si T est immutable mais je demande quand même)

    D'avance merci pour toute les explication partielles ou complètes =)

    • Partager sur Facebook
    • Partager sur Twitter
      30 novembre 2015 à 16:17:09

      Bonjour.

      Quand tu fais B=A alors l'objet B pointe vers le même objet A, donc les mêmes données à l'intérieur.

      Je t'invite à tester avec un exemple simple, c'est la meilleur façon de comprendre et d'apprendre.

      • Partager sur Facebook
      • Partager sur Twitter
      Angular 2 est l'avenir, jQuery c'est de la merde !!! - Java 8 c'est l'an 2016+ (programmez en 1 ligne)
        1 décembre 2015 à 10:20:00

        Je m'en suis bien rendu compte, sauf que après que B pointe vers A, toute action sur A se fera aussi sur B (référence oblige).

        Donc comment faire pour que B récupère uniquement les données de A (sans clonage si l'ummutabilite des classes est effective) ?

        Edit :

        B = new T(A);

        Avec un constructeur qui va bien me crée une copie de A. Seulement lors de la modification de A, cela joue toujours sur B. Je creuse encore !

        -
        Edité par BabC 1 décembre 2015 à 10:50:05

        • Partager sur Facebook
        • Partager sur Twitter
          1 décembre 2015 à 11:19:55

          Tu as la méthode clone() : je ne me suis pas assez documenter pour critiquer cette technique.
          Tu as aussi la méthode avec un "constructeur par copie" (comme tu l'as cité).

          Par contre si tu ne fais qu'une simple affectation des attributs dans ton objet copié, l'attribut pointe vers le même objet, donc tu reviens au problème initial mais au niveau des attributs.

          Exemple :

          Ici tes 2 objets foo et bar pointent vers le même objet en mémoire :

          class Person {}
          
          // -- copie
          Person foo = new Person();
          Person bar = foo;
          // égalité
          foo == bar

          Ici tes 2 objets foo et barr sont biens différents en mémoire, par contre leur attribut address est exactement le même en mémoire :

          class Address {}
          class Person {
              Address address;
              Person(Person other) {
                  this.address = other.address;
              }
          }
          
          // copie
          Person foo = new Person();
          Person bar = new Person(foo);
          // égalité
          foo != bar
          foo.address == bar.address
          

          Il faudrait refaire la même chose au niveau d'Address, et on n'en finie jamais !

          Par contre la problématique est différente pour les types primitifs, car tu copies la valeur :

          class Person {
              int age;
              Person(int age) {
                  this.age = age;
              }
              Person(Person other) {
                  this.age = other.age;
              }
          }
          
          // copie
          Person foo = new Person(13);
          Person bar = new Person(foo);
          // égalité
          foo.age == bar.age == 13
          // modification
          foo.age = 42;
          // différence
          foo.age == 42
          bar.age == 13
          • Partager sur Facebook
          • Partager sur Twitter
          Angular 2 est l'avenir, jQuery c'est de la merde !!! - Java 8 c'est l'an 2016+ (programmez en 1 ligne)
            1 décembre 2015 à 16:19:18

            On en finit lorsque l'attribut est composé que de type primitif du coup ... ? (si Adresse est un String + int par exemple, rendre Adresse immutable avec une copie par constructeur).

            Concernant la copie de tableau de type non primitif (ou même primitif), ça se passe comment ? Car en ayant fait

            public T(T A){
             this.tab = A.tab
            }
            
            //ou
            
            public T(T A){
             this.tab = new Tab[A.tab.length]
             for (int i = 0 ; o < tab.length ; i++){
              this.tab[i] = A.tab[i];
             } 
            }
            

            et B = new T (A);   J'ai une modification de B alors que j’agis uniquement sur A... Du coup il doit me manquer quelque chose ...

            • Partager sur Facebook
            • Partager sur Twitter
              1 décembre 2015 à 16:22:50

              En gros oui, tu résoudra le problème en arrivant aux types primitifs.
              String est un cas particulier à cause de la String pool, car tu pointeras sur le même objet en mémoire.

              Vois les tableaux comme une classe : si tu veux un new Tab[...] tu crées un nouvel espace mémoire, mais lorsque tu feras la copie directement de l'un vers l'autre, dans ton tableau tes objets pointeront vers le même espace mémoire.

              • Partager sur Facebook
              • Partager sur Twitter
              Angular 2 est l'avenir, jQuery c'est de la merde !!! - Java 8 c'est l'an 2016+ (programmez en 1 ligne)
                3 décembre 2015 à 11:51:30

                Merci pour tes reponses

                Pinguet62 a écrit:

                 dans ton tableau tes objets pointeront vers le même espace mémoire.


                Sauf si c'est un type primitif du coup :

                	 int[] tab1 = {0,1};
                	 int[] tab2 = {2,3};
                	 tab2 = new int[]{tab1[0],tab1[1]};
                	 tab1[0] = 4;
                	 System.out.println(tab2[0]);

                J'obtiens 0 alors qu'avec

                	 int[] tab1 = {0,1};
                	 int[] tab2 = {2,3};
                	 tab2 = tab1;
                	 tab1[0] = 4;
                	 System.out.println(tab2[0]);

                J'obtiens 4 (ce que je ne veux pas)


                • Partager sur Facebook
                • Partager sur Twitter
                  3 décembre 2015 à 12:02:37

                  Et bien un tableau c'est exactement comme un objet, où les cases du tableau sont des attributs d'un objet :

                  Type[] array = { val1, val2 };
                  
                  class Array {
                      Type index1 = val1;
                      Type index2 = val2;
                  }
                  • Partager sur Facebook
                  • Partager sur Twitter
                  Angular 2 est l'avenir, jQuery c'est de la merde !!! - Java 8 c'est l'an 2016+ (programmez en 1 ligne)
                    3 décembre 2015 à 14:38:13

                    J'ai finit de rendre immutable mes classes avec tes conseils/indications.

                    Je passe donc par une copie par constructeur, dans lequel je copie mes types primitfs (this.p = copie.p) ou je crée un nouvel espace mémoire pour mes objets (this.o = new o) et je copie par la suite les types primitifs de l'attribut 'o' (this.o.id = copie.o.id). Idem pour mes tableaux de type primitif ou objet.

                    Cela suffit a avoir deux objets distincts en mémoire mais identique en contenu.

                    Lorsque que je balance mon projet sur l'application sur laquelle je travaille, je n'ai aucun soucis d’accès, de blocage (multithreading) ou autre pour le moment ! Il faut encore que je regarde en détail avec jmc mais c'est déjà prometteur =)

                    • Partager sur Facebook
                    • Partager sur Twitter

                    [Question] Immutabilite et copie d'objet

                    × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                    × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                    • Editeur
                    • Markdown