Question

Je suis en train de mettre en œuvre une méthode de clone() sur un DoubleLinkedList. Maintenant, le problème est que la mise en œuvre par « la convention » est beaucoup plus difficile que de créer un nouveau DoubleLinkedList et le remplir avec tous les éléments de mon DoubleLinkedList actuel.

Y at-il pratique je ne vois pas quand le faire?

Voici mon approche actuelle:

@Override
public DoubleLinkedList<T> clone() {
    DoubleLinkedList<T> dll = new DoubleLinkedList<T>();

    for (T element : dll) {
        dll.add(element);
    }

    return dll;
}

Voici ce qu'il serait par la convention:

@Override
public DoubleLinkedList<T> clone() {
    try {
        DoubleLinkedList<T> dll = (DoubleLinkedList<T>)super.clone();
        //kinda complex code to copy elements
        return dll;
    } catch (CloneNotSupportedException e) {
        throw new InternalError(e.toString());
    }
}
Était-ce utile?

La solution

Comme vous l'avez à juste titre, la convention est de super.clone() toujours appel au début d'une mise en œuvre de clone(). De l'API docs sur Object#clone() :

Par convention, l'objet retourné doit être obtenu en appelant super.clone. Si une classe et toutes ses superclasses (sauf objet) obéissent à cette convention, ce sera le cas que x.clone (). GetClass () == x.getClass ().

Votre première tentative (sans utiliser super.clone()) a le problème suivant:

Supposons que j'ai

class IntDoubleLinkedList extends DoubleLinkedList<Integer> implements Cloneable

(et que IntDoubleLinkedList ne se soucie pas de forçage clone()) et j'exécuter le code suivant:

IntDoubleLinkedList idll = new IntDoubleLinkedList();
IntDoubleLinkedList idll2 = (IntDoubleLinkedList) idll.clone();

Qu'est-ce qui va se passer? La méthode clone de votre DoubleLinkedList seront exécutés, qui, si elle ne passe pas par super.clone (), renvoie une instance de DoubleLinkedList qui à son tour ne peut pas être casté à un IntDoubleLinkedList. Un ClassCastException sera lancé!

Alors, comment super.clone() résoudre ce problème? Eh bien, si tout le monde bâton à la convention d'appeler super.clone() dans une méthode clone surchargée, Object.clone() sera finalement appelé, et cette mise en œuvre va créer une instance d'un type approprié (IntDoubleLinkedList dans ce cas)!

Autres conseils

Comme d'autres l'ont expliqué, si vous allez override clone vous devez obéir à son contrat.

Si vous aimez la façon dont vous avez actuellement, juste faire DoubleLinkedList pas Cloneable et transformer votre application en un constructeur de copie ou d'une méthode d'usine statique. Une méthode de fabrique statique a l'avantage de fournir un peu de type pour les arguments de l'inférence de type générique, aussi.

P.S. LinkedList une liste doublement chaînée.

Si vous le faites en créant une nouvelle liste et en ajoutant tous les éléments de la source, si vous faire quelque chose comme:

DoubleLinkedList<Foo> l1 = new DoubleLinkedList<Foo>();
l1.add (new Foo(params));
DoubleLinkedList<Foo> l2 = l1.clone();
Foo foo = l2.get(0);
foo.setProperty("new Value");

foo.property sera « nouvelle valeur » dans les deux listes (même l'inverse, si vous changez en l1, les changements apparaissent dans l2). La manière correcte serait de cloner en fait tous les éléments et ajouter le clone pour que les listes sont indépendantes. Prenez note que cela ne se produit si vous modifiez les propriétés des éléments, pas si vous ajoutez, déplacez les supprimer de la liste.

Edit:. Viens de réaliser que puisqu'il est une liste liée, les éléments suivant / précédent sont des propriétés de l'élément, de sorte que même l'ajout, la suppression, affectera à la fois la liste

La raison pour laquelle la « convention » est d'appeler super.clone() est d'assurer le type ultime de l'objet cloné correspond à l'objet qui est cloné. Par exemple, si vous instanciez votre nouvelle DoubleLinkedList dans la méthode clone(), bien que pour l'instant est agréable, mais plus tard, si une sous-classe ne parvient pas à passer outre clone() il va finir par revenir un clone qui est un DoubleLinkedList au lieu de sa propre classe. (Il va également cloner ses ne parviennent pas à des champs supplémentaires, le cas échéant, sans doute! Donc il y a des problèmes plus importants.)

En ce sens, le procédé classique est préféré, et il est en effet maladroit.

Les deux implémentations ont cependant un problème similaire: vous n'êtes pas en profondeur la copie des structures de données. Le clone est seulement un flic peu profond. Ceci est probablement pas ce que l'appelant attend. Vous devrez passer par et remplacer chaque valeur dans le DoubleLinkedList avec un clone de la valeur, et de même pour d'autres domaines non primitifs.

En ce sens, la méthode classique va donner ici le mauvais résultat! Vous avez besoin d'une troisième voie. Votre première méthode probablement à peu près œuvres, sauf que vous devez ajouter element.clone() par exemple.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top