Interface clonable obligatoire en Java


J'ai un petit problème en Java. J'ai une interface appelée Modifiables. Les objets implémentant cette interface sont modifiables.

J'ai aussi une classe ModifyCommand (avec le modèle de commande) qui reçoit deux objets modifiables (pour les échanger dans une liste plus loin - ce n'est pas ma question, j'ai déjà conçu cette solution).

La classe ModifyCommand commence par créer des clones des objets modifiables. Logiquement, j'ai rendu mon interface Modifiable Clonable. Le interface définit ensuite une méthode clone () que ses classes d'implémentation doivent redéfinir.

Ensuite, dans ModifyCommand, je peux faire : firstModifiableObject.clone(). Ma logique est que les classes implémentant Modifiable devront redéfinir la méthode clone à partir d'Object, car elles seront Clonables (c'est ce que je veux faire).

Le fait est que lorsque je définis des classes implémente Modifiable et que je veux remplacer clone (), il ne me le laissera pas, indiquant que la méthode clone () de la classe Object cache le l'un de Modifiable.

Que dois-je faire? J'ai l'impression que "je le fais mal"...

Merci,

Guillaume.

Edit : il pense que je vais oublier la chose clone (). Je vais soit a) supposer que l'objet transmis à l'objet modifiable (implémentant l'interface) est déjà cloné ou b) faire une autre méthode appelée, par exemple, copy(), qui ferait essentiellement une copie en profondeur de l'objet Modifiable (ou peut-être que la solution générique fonctionnera...).

Author: Guillaume Gervais, 2008-10-27

6 answers

Si vous utilisez java 1.5 ou supérieur, vous pouvez obtenir le comportement souhaité et supprimer le casting de cette façon:

public interface Modifiable<T extends Modifiable<T>> extends Cloneable {
    T clone();
}

public class Foo implements Modifiable<Foo> {
    public Foo clone() { //this is required
        return null; //todo: real work
    }
}

Puisque Foo étend Object, cela satisfait toujours le contrat d'origine de la classe Object. Le code qui n'affine pas correctement la méthode clone () ne sera pas compilé, en raison des contraintes supplémentaires imposées par l'interface Modifiable. En prime, le code appelant n'a pas besoin de lancer le résultat de la méthode clone.

 10
Author: Sean Reilly, 2008-12-30 15:52:33

Vous n'avez pas besoin de redéfinir la méthode clone sur l'interface Modifiable.

, consultez la documentation: http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Cloneable.html

Je comprends que vous essayez de forcer tout le monde à remplacer clone method(), mais vous ne pouvez pas le faire.

D'une autre manière, vous ne pouvez pas remplacer une classe sur une interface:

La méthode clone() est toujours associée à l'objet.classe et non l'interface cloneable. Vous ne pouvez remplacez-le sur un autre objet, pas dans une interface.

 1
Author: sakana, 2008-10-27 17:51:21

En ajoutant à la réponse de Sean Reilly, cela devrait résoudre votre problème et est plus sûr. Il compile et fonctionne bien avec moi sur JDK6:

public interface Modifiable<T extends Modifiable<T>> extends Cloneable {
    T clone();
}
public class Test implements Modifiable<Test> {
    @Override
    public Test clone() {
        System.out.println("clone");
        return null;
    }
    public static void main(String[] args) {
        Test t = new Test().clone();
    }
}

Je n'ai pas pu le tester avec Java 5 parce que je ne l'ai pas installé, mais je suppose que cela fonctionnerait bien.

 1
Author: Hosam Aly, 2008-12-23 06:44:37

Avez-vous défini la signature exactement telle qu'elle est dans l'objet?

public Object clone() throws CloneNotSupportedException {
    return super.clone();
}

Cela devrait compiler - ajouter du code personnalisé au corps. Wikipedia a été étonnamment utile sur celui-ci.

 0
Author: Chris Marasti-Georg, 2008-10-27 17:47:37

À quoi ressemble votre signature de méthode pour votre méthode clone? Pour qu'il corresponde à l'interface Clonable, il devrait renvoyer un objet. Si vous le déclarez comme renvoyant un Modifiable, cela pourrait être le problème.

 0
Author: Herms, 2008-10-27 17:48:37

La classe publique CloningExample implémente Cloneable {

private LinkedList names = new LinkedList();


public CloningExample() {
    names.add("Alex");
    names.add("Melody");
    names.add("Jeff");
}


public String toString() {
    StringBuffer sb = new StringBuffer();
    Iterator i = names.iterator();
    while (i.hasNext()) {
        sb.append("\n\t" + i.next());
    }
    return sb.toString();
}


public Object clone() {
    try {
        return super.clone();
    } catch (CloneNotSupportedException e) {
        throw new Error("This should not occur since we implement Cloneable");
    }
}


public Object deepClone() {
    try {
        CloningExample copy = (CloningExample)super.clone();
        copy.names = (LinkedList)names.clone();
        return copy;
    } catch (CloneNotSupportedException e) {
        throw new Error("This should not occur since we implement Cloneable");
    }
}

public boolean equals(Object obj) {

    /* is obj reference this object being compared */
    if (obj == this) {
        return true;
    }

    /* is obj reference null */
    if (obj == null) {
        return false;
    }

    /* Make sure references are of same type */
    if (!(this.getClass() == obj.getClass())) {
        return false;
    } else {
        CloningExample tmp = (CloningExample)obj;
        if (this.names == tmp.names) {
            return true;
        } else {
            return false;
        }
    }

}


public static void main(String[] args) {

    CloningExample ce1 = new CloningExample();
    System.out.println("\nCloningExample[1]\n" + 
                       "-----------------" + ce1);

    CloningExample ce2 = (CloningExample)ce1.clone();
    System.out.println("\nCloningExample[2]\n" +
                       "-----------------" + ce2);

    System.out.println("\nCompare Shallow Copy\n" +
                       "--------------------\n" +
                       "    ce1 == ce2      : " + (ce1 == ce2) + "\n" +
                       "    ce1.equals(ce2) : " + ce1.equals(ce2));

    CloningExample ce3 = (CloningExample)ce1.deepClone();
    System.out.println("\nCompare Deep Copy\n" +
                       "--------------------\n" +
                       "    ce1 == ce3      : " + (ce1 == ce3) + "\n" +
                       "    ce1.equals(ce3) : " + ce1.equals(ce3));

    System.out.println();

}

}

 0
Author: , 2009-05-14 03:11:52