Cloneable

helloworld95 -  
KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   -
Bonjour,

Toujours dans ma classe Client, j'aimerai éviter quelle référence toujours la même commande.

Si j'ajoute un article dans les
Exemple:

public class TestAttribut {
	public static void main(String[] args) {
		Client client = new Client("Robert", "Michel");
		Commande commande = new Commande(2, LocalDateTime.now());
		commande.ajouterArticle(new Article(1, "Nespresso", 5));
		client.enregistrerCommande(commande);
		System.out.println(client.getCommande());
		
		//ajouter un article ne doit pas modifier la commande du client
		commande.ajouterArticle(new Article(2, "Cappuccino", 7.50));
		System.out.println(client.getCommande());
	}
}


J'ai donc essayer avec un clone mais ce ne fonctionne pas.

Dans commande :
	@Override
	protected Commande clone() throws CloneNotSupportedException{
		return (Commande) super.clone();
	}


Dans Client :
	public void enregistrerCommande(Commande commande) throws CloneNotSupportedException{
		this.commande = commande.clone();
	}


Comment faire dans ce cas ?



2 réponses

Jithel Messages postés 843 Date d'inscription   Statut Membre Dernière intervention   171
 
Le code n'est pas complet (code de commande notamment).

La classe Commande implémente bien l'interface Cloneable ?
Une erreur lors de la compilation ou de l'exécution ?
0
helloworld95
 
Aucune erreur de compilation

public class Commande implements Cloneable {
	
	private int numero;
	private LocalDateTime date;
	List<Article> listeArticles;

	public Commande(int numero, LocalDateTime date) {
		this.numero = numero;
		listeArticles = new ArrayList<>();
	}
	
	public boolean ajouterArticle(Article article) {
		if (listeArticles.contains(article))
			return false;
		listeArticles.add(article);
		return true;
	}
	
	public int getNumero() {
		return numero;
	}

	public LocalDateTime getDate() {
		return date;
	}
	
	@Override
	public String toString() {
		return this.numero + " " + listeArticles.toString();
	}

	@Override
	protected Commande clone() throws CloneNotSupportedException{
		return (Commande) super.clone();
	}
}
0
KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   3 020
 
Bonjour,

Ton code est bon, c'est le main() qui t'induit en erreur.
Tu as mis le clone() dans la méthode enregistrerCommande() mais tu ne l'appelle pas...

Avec ce main, c'est bon, ton clone() est bien effectif :
Commande c1 = client.getCommande();
client.enregistrerCommande(commande);
Commande c2 = client.getCommande();
System.out.println(c1 == c2); // false
0
helloworld95
 
Je n'ai pas très bien compris le principe...
Mais dans le cas ci dessous par exemple, il ajoute quand même les articles dans la commande du client sans passer par enregistrerCommande() mais directement par l'objet Commande. Est-ce possible de l'eviter ?
Commande c2 = client.getCommande();
System.out.println(c2);
commande.ajouterArticle(new Article(3, "Latte", 3.50));
Commande c3 = client.getCommande();
System.out.println(c3); // output les 3 articles de la liste
0
KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   3 020 > helloworld95
 
Déjà, pour moi ce que tu fait n'as pas trop de sens, tu ne peux pas avoir une commande l'enregistrer, puis la modifier à nouveau. Si la commande est enregistrée c'est fini, tu ne devrais ni pouvoir ajouter d'articles, ni pouvoir enregistrer à nouveau une commande déjà enregistrée.

Si on était sur un site marchand, tu aurais deux notions biens distinctes, le "panier" que tu remplis d'articles au fur et à mesure et la commande que tu obtiens une fois le panier validé (et le paiement accepté...)

Ce qui aurait plus du sens, en programmation objet, ce serait.
Panier panier = new Panier();
panier.ajouterArticle(article1, quantité1);
panier.ajouterArticle(article2, quantité2);
Commande commande = panier.enregistrerCommande();

Remarque : cela fait plusieurs années que je programme en Java et jamais je n'ai réellement eu besoin de clone().
Il y a d'autres mécanismes bien meilleurs pour faire les choses proprement. Voir Java Practices → avoid clone
0
helloworld95
 
Je suis d'accord que l'exemple n'est peu etre pas le meilleur choisi (on ne modifie pas une commande après l'avoir passé) mais ce que j'essaye de faire c'est empecher qu'on modifie un attribut via un objet extérieur (ici l'objet commande)
0
KX Messages postés 16761 Date d'inscription   Statut Modérateur Dernière intervention   3 020 > helloworld95
 
Tu pourrais utiliser Collections.unmodifiableList pour protéger ta liste.

public class Commande {
	private final List<Article> listeArticles;

	public List<Article> getArticles() {
	    return Collections.unmodifiableList(listeArticles);
	}
}

List<Article> articles = commande.getArticles();
articles.add(new Article(3, "Latte", 3.50)); // UnsupportedOperationException
0