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 :

≠ Copie profonde & Copie de surface


Sujet :

avec Java

  1. #1
    Membre à l'essai
    Homme Profil pro
    Webplanneur
    Inscrit en
    Décembre 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Webplanneur
    Secteur : Bâtiment

    Informations forums :
    Inscription : Décembre 2014
    Messages : 24
    Points : 16
    Points
    16
    Par défaut ≠ Copie profonde & Copie de surface
    Bonsoir,

    Je cherche à saisir parfaitement la différence entre copie de surface et copie profonde:

    Ce que j'ai saisie:

    Copie de surface( ou encore copie séquentielle)
    Un nouvelle objet est instancié et ses attributs pointent par référence sur les attributs de l'objet parent.
    Si les valeurs de l'attribut de l'objet copié sont modifiés, les valeurs de l'attributs de l'objet parent aussi.

    Copie profonde
    Un nouvelle objet est instancié et ses attributs sont des copie de l'objet parent , de plus ils sont totalement indépendants et leurs valeurs peuvent être modifiées sans que cela modifie les valeurs d'attributs de l'objet parent, car il n'y pas de passage par référence.

    Est ce que je me trompe ?

    Pourriez vous également m'indiquer un cas d'utilisation de ces 2 types de copies svp ?

  2. #2
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par reymsKoola Voir le message
    Copie de surface( ou encore copie séquentielle)
    Un nouvelle objet est instancié et ses attributs pointent par référence sur les attributs de l'objet parent.
    Si les valeurs de l'attribut de l'objet copié sont modifiés, les valeurs de l'attributs de l'objet parent aussi.
    Non. Les attributs sont tous bien copies dans le nouvel objet. Pour les attributs qui sont des références vers d'autres objets, ce sont les références qui sont copiée et non pas les objet. Ainsi, pour ces attributs là, les attributs de la source et du nouvel objets pointent vers les mêmes objets.

    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
     
    public class X {
       int a = 5;
       Dimension d = new Dimension(25,25);
    }
     
    X x1 = .....;
    X x2 = copieDeSurface(x1);
    x1.a = 6;
    x1.d.setDimension(50,50);
    x2.a == 5; //(et non pas 6)
    x2.d.getWidth() == 50; //x2 voit biens le même objet dimension que x1
    x1.d = new Dimension(75,75);
    x2.d.getWidth() == 50; //mais x1 et x2 on bien chacun leur attribut d, si je change la référence d dans X1 ca n'influence pas X2 et vice versa.
    Copie profonde
    Tout est copié recursivement, il n'y a pas de référence vers des objets commun entre la source et la destination.


    Copie de surface: la plus utilisée, ont s'en sert quand on n'a besoin que de manipuler le premier niveau ou que l'on veux que les niveaux inférieurs restent synchrones.
    Exemples:

    Un jeu de carte, 52 cartes, chaque carte a une valeur et une couleur.
    A partir d'une position de départ, je veux simuler différentes manières de couper le paquet en deux: je prend le paquet du dessous et je le met au dessus.
    Je vais donc, pour chaque combinaison, prendre le paquet de départ, faire une copie de surface, et réorganiser le paquet copié. Je ne vais pas copier l'attribut cartes de manière profonde car elles restent les mêmes. Je ferais donc ceci:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    List<Carte> paquetDeDepart = ....
    List<Carte> combinaisonEnCours = new ArrayList<Carte> (paquetDeDepart);
    qui me crée une nouvelle liste, avec les mêms objets Carte et non pas des copies.


    Copie profonde: j'ai un objet Client, avec son adresses, ses commandes, etc. Il viens de la partie interne de mon programme et ne dois pas être modifié. Par sécurité, l'appel getClient() retournera une copie profonde de ce que j'ai en mémoire afin que l'appelant puisse faire ce qu'il veux avec le Client sans m'affecter. Il le jettera simplement quand il aura fini avec.

    La copie profonde prend plus de mémoire, et plus longue à coder et peut parfois s'avérer complexe si l'objet de départ a beaucoup de relations en boucle. Souvent on travail aussi avec un mix, certaines données sont copié profondément, d'autre pas. Ca dépend du besoin.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Webplanneur
    Inscrit en
    Décembre 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Webplanneur
    Secteur : Bâtiment

    Informations forums :
    Inscription : Décembre 2014
    Messages : 24
    Points : 16
    Points
    16
    Par défaut
    Ainsi, pour ces attributs là, les attributs de la source et du nouvel objets pointent vers les mêmes objets
    Si il y a un nouvel objet , comment font ils pour pointer vers d'autres mêmes objets, je croyais que l'on pointait sur des attributs ?
    Si je reprend: copie de surface:
    Un nouvel objet est instancié, les attributs sont copiés et ils pointent tous les deux (attributs parents et enfants) vers une même référence ?

    Je t'avoue ne plus rien comprendre

    Dans ce code je t'avoue m'y perdre aussi ... j'ai laissé quelques commentaires
    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
    public class X {
       int a = 5;
       Dimension d = new Dimension(25,25);
    }
     
    X x1 = .....;  // Instancier avec constructeur par  défaut ? donc a =5 et d = 25,25 ? ou j'imagine les valeurs ??
    X x2 = copieDeSurface(x1); 
    x1.a = 6;  // euh pourquoi 6 ? ce ne serait pas 5 parce que on n'a jamais modifié a ?
    x1.d.setDimension(50,50);
    x2.a == 5; //(et non pas 6) // je me trompe surement, mais je croyais que '=' était le seul opérateur d'affectation et que '==' signifiait 'égal à' 
    // dans le cas où 'égal à' est bien ce que tu voulais dire, comment pourrais je confondre ? étant donné que a = 5 dans la classe X
    x2.d.getWidth() == 50; //x2 voit biens le même objet dimension que x1  // d'accord pour cette ligne
    x1.d = new Dimension(75,75); 
    x2.d.getWidth() == 50; //mais x1 et x2 on bien chacun leur attribut d, si je change la référence d dans X1 ça n'influence pas X2 et vice versa.
    // euh changer la référence ? si des attributs pointent sur une même référence, si on modifie un des attributs on modifie tous les attributs de la référence ?
    Pour l'exemple du jeu de carte je ne saisie pas non plus ... je ne suis pas de ton niveau ...

    Si tu pouvais me réexpliquer avec des choses simples comme [...]ville(nom, pays)[...] si çà ne te dérange pas stp.

  4. #4
    Expert éminent sénior
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 481
    Points : 48 806
    Points
    48 806
    Par défaut
    Citation Envoyé par reymsKoola Voir le message
    je croyais que l'on pointait sur des attributs ?
    Jamais, on référence des objets, on stocke dans des attributs des références vers ces objets. On ne stocke jamais un objet dans un attribut., contrairement au C++. En java, un objet et toujours manipulé via une référence. Quand je fais un new XYZ() en java, je crée un Object XYZ, et l'opérateur new me revoie une référence vers cet objet. Cette référence, j'irais ensuite la stocker dans une attribut, dans une variable, je la passerais à une méthode ou je l'ignorerais, au choix.



    On peut stocker dans un attribut soit
    une valeur simple (int, boolean, char, float, ...)
    une référence vers un objet (String, int[], List<String>, JFrame, .....)


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public class X {
       int a = 123;
       double b = 1.5;
       String c = "Hello";
       Integer d = 8;
       Map e = new HashMap();
    }
    a et b stockent des valeurs simple, c d et e stockent des références, respectivement vers une objet représentant "Hello", vers un objet représentant 8 et vers une HashMap.


    Citation Envoyé par reymsKoola Voir le message
    Si je reprend: copie de surface:
    Un nouvel objet est instancié, les attributs sont copiés et ils pointent tous les deux (attributs parents et enfants) vers une même référence ?
    Oui



    Citation Envoyé par reymsKoola Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    X x1 = .....; // Instancier avec constructeur par défaut ? donc a =5 et d = 25,25 ? ou j'imagine les valeurs ??
    J'aurais pu mettre new X() effectivement. Les ... veulent juste dire 'peu importe comment on le récupère le X'
    Citation Envoyé par reymsKoola Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    x1.a = 6; // euh pourquoi 6 ? ce ne serait pas 5 parce que on n'a jamais modifié a ?
    Ben justement, c'est que fait la ligne, mettre la valeur 6 dans X1.a, ce n'est pas un test d'égalité
    Citation Envoyé par reymsKoola Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    x2.a == 5; //(et non pas 6) // je me trompe surement, mais je croyais que '=' était le seul opérateur d'affectation et que '==' signifiait 'égal à'
    Ben oui, ça me semblait clair, je te dit que x2.a est bien toujours égal (test d'égalité) à 5
    Citation Envoyé par reymsKoola Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    // dans le cas où 'égal à' est bien ce que tu voulais dire, comment pourrais je confondre ? étant donné que a = 5 dans la classe X
    Vu que tu pensais qu'on pointais vers les attributs, tu aurais pu confondre, donc je précise
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    x2.d.getWidth() == 50; //mais x1 et x2 on bien chacun leur attribut d, si je change la référence d dans X1 ça n'influence pas X2 et vice versa.
    Citation Envoyé par reymsKoola Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    // euh changer la référence ? si des attributs pointent sur une même référence, si on modifie un des attributs on modifie tous les attributs de la référence ?
    x1.d est un attribut qui stocke une référence vers un Objet Dimension. Comme j'ai changé la référence présente dans x1.d en faisant x1.d = new Dimension(....), x1.d référence maintenant un nouvel objet (appelons le dimension 2) différent de celui que référence x2.d. Donc si je modifie des valeurs dans cet Objet "dimension 2", ça ne se voit pas depuis x2.d car ce n'est pas le même objet.

    Dans ce code je t'avoue m'y perdre aussi ... j'ai laissé quelques commentaires


    Pour l'exemple du jeu de carte je ne saisie pas non plus ... je ne suis pas de ton niveau ...

    Si tu pouvais me réexpliquer avec des choses simples comme [...]ville(nom, pays)[...] si çà ne te dérange pas stp.[/QUOTE]

  5. #5
    Membre à l'essai
    Homme Profil pro
    Webplanneur
    Inscrit en
    Décembre 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Webplanneur
    Secteur : Bâtiment

    Informations forums :
    Inscription : Décembre 2014
    Messages : 24
    Points : 16
    Points
    16
    Par défaut
    J'y vois déjà plus claire et ton code prend tout son sens en effet.

    Donc chaque objet a bien le même attribut mais avec dans des variables différentes contenant la même référence, j'en deviens logique en voyant mon constructeur par copie

    Sinon une dernière chose que je ne comprend pas du coup ... quel différence avec la copie profonde ?

    La copie de surface: elle copie chaque attribut source en copiant la référence des valeurs de chaque attribut source dans les nouvelles variables de l'objet de destination.

    La copie profonde: elle copie chaque attribut sans copier les références (mais bien en copiant les valeurs) dans de nouvelles variables de l'objet de destination.

    Si au bout du compte (que ce soit par copie de surface ou profonde) on travaille sur des variables différentes qui n'affecte ni l'objet source ni l'objet de destination ne s'affecte pas mutuellement en cas de modification des valeurs des attributs, quel est l'utilité d'utilisation ? et l'utilité de le savoir ?
    mise à part le fait de moins utiliser de mémoire pour la copie de surface car elle ne recrée pas de cases de mémoires pour contenir la même valeur d'attribut que l'objet source.

    j'espère avoir bien saisie,

  6. #6
    Modérateur
    Avatar de kolodz
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2008
    Messages
    2 211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 211
    Points : 8 316
    Points
    8 316
    Billets dans le blog
    52
    Par défaut
    En effet, c'est globalement ce que tu as compris.

    La copie profonde est généralement réalisé dans des cas où l'on veux qu'une action sur l'objet A, n'impacte pas la grappe d'objet B copié et inversement. Cela peut-être le cas quand on réalise une copie de travail d'une grappe d'objet.

    Cependant, la copie de surface reste le cas le plus pratiqué. D'ailleurs, c'est ce que réalise la méthode clone() !

    Supposons le code suivant :

    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
    public class A implements Cloneable {
    	private int value = 0;
    	private A next;
     
    	public static void main(String[] args) throws CloneNotSupportedException {
    		A a = new A();
    		A b = new A();
    		b.value = 10;
    		a.value = 5;
    		a.next = b;
    		// Dans le cas ou on réalise une copie de a dans c
    		A c = (A) a.clone();
    		System.out.println(a.next == c.next);// Retourne True
    		a.next.value = 20;
    		System.out.println(c.next.value); // Retourne 20, car même objet
    		// Dans le cas où on réalise une copie profonde de a dans d
    		// Réalisation en deux lignes de la copie profonde à la main !
    		A d = (A) a.clone();
    		d.next = (A) a.next.clone();
     
    		System.out.println(a.next == d.next); // Retourne false
    		System.out.println(d.next.value); // Retourne 20 (Car même valeur )
    		a.next.value = 5;
    		System.out.println(d.next.value);// Retourne toujours 20, car non affecté par les modifications réalisé sur a
    		d.next.value = 10;
    		System.out.println(d.next.value); // Retourne 10, car on modifie l'objet directement
    		System.out.println(a.next.value); // Retourne 5, car pas d'effet sur la grappe d'objet a (Et on l'as mis à 5 juste avant)
     
    	}
    }
    Si une réponse vous a été utile pensez à
    Si vous avez eu la réponse à votre question, marquez votre discussion
    Pensez aux FAQs et aux tutoriels et cours.

  7. #7
    Membre à l'essai
    Homme Profil pro
    Webplanneur
    Inscrit en
    Décembre 2014
    Messages
    24
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Webplanneur
    Secteur : Bâtiment

    Informations forums :
    Inscription : Décembre 2014
    Messages : 24
    Points : 16
    Points
    16
    Par défaut
    super c'est clair enfin !

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

Discussions similaires

  1. Copie profonde sur classe paramétrée
    Par lepak dans le forum Langage
    Réponses: 3
    Dernier message: 07/10/2010, 16h46
  2. vb 6 : copie profonde d'un objet
    Par TaymouWan dans le forum VB 6 et antérieur
    Réponses: 1
    Dernier message: 10/08/2009, 11h04
  3. Copie profonde d'objets en C#
    Par sandre dans le forum C#
    Réponses: 7
    Dernier message: 23/08/2007, 13h11
  4. Copie Logique et copie physique
    Par GDMINFO dans le forum Langage
    Réponses: 6
    Dernier message: 16/04/2007, 11h53
  5. [VB.NET]Comment s'opère la copie profonde d'objet?
    Par NicolasJolet dans le forum VB.NET
    Réponses: 5
    Dernier message: 29/03/2006, 15h23

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