Bonjour,
j'ai une classe représentant une Personne, les attributs sont:
nom, prénom et sexe.
Je dois surcharger la méthode clone() en faisant un deep copy..
Je ne vois vraiment pas comment écrire cette méthode.
Pouvez vous m'aider?
Merci
Bonjour,
j'ai une classe représentant une Personne, les attributs sont:
nom, prénom et sexe.
Je dois surcharger la méthode clone() en faisant un deep copy..
Je ne vois vraiment pas comment écrire cette méthode.
Pouvez vous m'aider?
Merci
bonjour,
La réponse est la : clonage
Il n'y a pas de problème, il n'y a que des solutions.
Cependant, comme le disaient les shadoks, s'il n'y a pas de solution, c'est qu'il n'y a pas de problème.
Si toutefois le problème persiste, la seule solution restante est de changer le périphérique qui se trouve entre la chaise et l'écran
Mes Articles : Mon premier article est sur le language D
N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java
Il te suffit simplement d'implémenter la méthode clone dans ta Classe Personnes :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 @Override protected Object clone() throws CloneNotSupportedException { // TODO Auto-generated method stub return new Person(this.name, this.lastName, this.sexe); }
Salut,
Sauf que ceci est incorrect puisque tu ne respectes pas les règles du cloneage !
Il ne faut pas utiliser un constructeur mais appeler la méthode clone() hérité de Object, en implémentant Cloneable.
Exemple "basique" :
Il est inutile de dupliquer la valeur pour le "sexe", puisqu'il s'agit d'un type primitif et que le clone copiera alors sa valeur.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 class Person implements Cloneable { private String nom; private String prenom; private Date birthDay; private char sexe; @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); } }
Pour les références c'est un peu plus compliqué car c'est la copie de la référence qui est effectué. Donc les deux références pointent vers le même objet en mémoire et il faut donc protéger cela par une copie explicite... sauf pour les types immuables (comme String) où cela est inutile et même contre-productif !
Donc cela devrait plutôt ressembler à ceci :
Maintenant on peut encore améliorer cela de trois manière :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9 @Override protected Object clone() throws CloneNotSupportedException { Person cloned = (Person) super.clone(); // On duplique l'attribut birthDay, car il n'est pas immuable : cloned.birthDay = (Date) cloned.birthDay.clone(); return cloned; }
- En supprimant l'exception de la déclaration de méthode. En effet cette dernière ne remontera que dans le cas où l'on implémente plus Cloneable. Inutile de se trainer une tel exception. Il est préférable de la cacher :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 @Override public Object clone() { try { Person cloned = (Person) super.clone(); cloned.birthDay = (Date) cloned.birthDay.clone(); return cloned; } catch (CloneNotSupportedException e) { // On remonte l'exception englobé dans une RuntimeException, // afin d'être quand même averti d'un éventuel problème : throw new RuntimeException(e); } }- Selon les besoins, en déclarant le classe public afin de faciliter son utilisation depuis l'extérieur (ce qui est autorisé par le langage).
- Enfin, depuis Java 5.0 il est possible de changer le type de retour, afin d'éviter un nouveau cast en sortie...
Ce qui donnerait au final :
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 @Override public Person clone() { try { Person cloned = (Person) super.clone(); cloned.birthDay = (Date) cloned.birthDay.clone(); return cloned; } catch (CloneNotSupportedException e) { // On remonte l'exception englobé dans une RuntimeException, // afin d'être quand même averti d'un éventuel problème : throw new RuntimeException(e); } }
Merci pour votre aide, donc si ma classe contient des attributs qui sont uniquement des String, des int, des char et des double, je peux me contenter de:
?????????
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }
Autre question: en quoi cette méthode utilise le DEEP COPY?
Merci d'avance.
comme tu n'as que des types primitif, elle n'utilise pas le deep copy. Comme la javadoc le dit, l'implémentation dans Object utilise le "shallow copy". Pour chaque attribut mutable de ton objet, tu devra donc après faire, à la main, une nouvelle instance, comme adiguba te l'a montré avec un date.
Merci pour la réponse.
Mais si on me demande de faire une méthode clone() en utilisant une deep copy et que ma classe contient que des attributs de type double et string... Je fais quoi?
Bon je m'incruste mais je comprends pas en quoi ce qu'il y a dessus est une bonne pratique ???En supprimant l'exception de la déclaration de méthode. En effet cette dernière ne remontera que dans le cas où l'on implémente plus Cloneable. Inutile de se trainer une tel exception. Il est préférable de la cacher :
Code :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 @Override public Object clone() { try { Person cloned = (Person) super.clone(); cloned.birthDay = (Date) cloned.birthDay.clone(); return cloned; } catch (CloneNotSupportedException e) { // On remonte l'exception englobé dans une RuntimeException, // afin d'être quand même averti d'un éventuel problème : throw new RuntimeException(e); } }
CloneNotSupportedException peut être remonté dans le cas où l'objet n'implémente pas l'interface clonable mais aussi dans le cas où la méthode a été overridé et que l'objet ne devrait pas être cloné.
Dans le deuxième cas ne vaudrait il mieux pas laisser le throws CloneNotSupportedException ??
Merci de m'éclairer
Il n'est pas très correct que le type courant soit cloneable mais qu'un type enfants ne le soit plus. Et si c'était le cas le type fils pourrait utiliser une RuntimeException...
L'idée est d'éviter de se trainer une exception inutile dans 99% des cas, et qui risque d'être ignorée, ce qui pourrait s'avérer bien pire.
a++
D'accord.
Si Personne ne contenait que des types primitifs et String, je pourrais me contenter de ceci:
Ou il vaut mieux faire ceci:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }
??
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 @Override protected Object clone() throws CloneNotSupportedException { Person cloned = (Person) super.clone(); return cloned; }
Merci d'avance.
Merci
Dernière chose: est ce mieux de mettre la méthode en protégé:
Ou en public:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 @Override protected Object clone() throws CloneNotSupportedException { return super.clone(); }
??
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 @Override public Object clone() throws CloneNotSupportedException { return super.clone(); }
tout dépend de qui a besoin de cloner ton objet. Mais a priori, en public ce serait quand meme le plus propre
D'accord
Deux toutes dernières choses:
- pourquoi mettre protected Object clone()...
et non protected Person clone()... ?
- ma classe Person doit obligatoirement impémenter cloneable()?
Merci
La covariance de type de retour d'une méthode est une fonctionnalité valable qu'à partir de java 5, Avant et par principe on ne peut redéfinir une méthode qui a la même signature où on change juste le type de retour:
càd avant java 1.5
Il est préférable d'utiliser cette fonctionnalité qui va t'éviter de faire des cast inutile..
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 class A{ public A method(); } class B extends A{ public B method(); } //Génère une erreur de compilation
Enfin OUI il faut implémenter Cloneable sinon on aura une CloneNotSupportedException quand tu va appeler Person.clone()
Oui, ta classe doit impérativement implémenter Cloneable. Sans quoi tu auras à coup sûr une CloneNotSupportedOperation.
La méthode clone() est protected dans Object afin d'avoir une implémentation par défaut invisible à l'extérieur. Tu peux la rendre accessible en la marquant public lorsque tu implémentes clone();
Je te conseille vraiment de prendre la méthode telle qu'Adiguba l'a écrite, bien que je remplacerais "throw new RuntimeException" par "throw new UnsupportedOperationException", mais bon, les goûts et les couleurs...
Moi je suis d'accord avec adiGuba pour l'exception RuntimeException qui va encapsuler l'exception non runtime juste pour éviter d'avoir des try catch inutiles en appelant clone()
UnsupportedOperationException va induire l'utilisateur à l'erreur en croyant qu'on ne peut appeler clone() alors qui a eu peut être une erreur interne c'est tout!
Comme je le disais, les goûts et les couleurs... La réponse d'adiguba suffisait amplement, mais tu désires que j'argumente donc
Petit exercice de comparaison de String :
- CloneNotSupportedException
- UnsupportedOperationException
Indice, cela se trouve en gras
Le choix qu'on a entre RuntimeException et UnsupportedOperationException est plus sémantique qu'autre chose : préfère-t-on lancer une IOException ou une Exception ? Je suis partisan de l'IOException, d'autres en ont rien à faire et lancent une Exception. C'est pareil ici, sauf qu'elle ne sera a priori jamais lancée.
À y réfléchir, ne serait-il pas plus correct de lancer une Error dans ce cas ?
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager