2008-10-27 17 views
4

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

J'ai aussi une classe ModifyCommand (avec le pattern Command) 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 démarre en créant des clones des objets modifiables. Logiquement, j'ai fait que mon interface Modifiable étend Cloneable. L'interface définit ensuite une méthode clone() que ses classes d'implémentation doivent redéfinir. Puis, dans ModifyCommand, je peux faire: firstModifiableObject.clone(). Ma logique est que les classes implémentant Modifiable devront redéfinir la méthode clone depuis Object, car elles seront Cloneable (c'est ce que je veux faire). Le fait est que, quand je définis des classes implémente Modifiable et que je veux écraser clone(), il ne me le permet pas, indiquant que la méthode clone() de la classe Object cache celle de Modifiable.

Que dois-je faire? Je suis sous l'impression que "je le fais mal" ...

Merci,

Guillaume. Edit: il pense que j'oublierai la chose clone(). Je vais a) supposer que l'objet passé à 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 profonde de l'objet Modifiable (ou peut-être que la solution générique fonctionnera ...).

Répondre

9

Si vous utilisez Java 1.5 ou supérieur, vous pouvez obtenir le comportement que vous voulez et enlever la coulée 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 
    } 
} 

Depuis Foo extends Object, cela satisfait encore le contrat initial de la classe d'objets.Le code qui ne raffine pas la méthode clone() correctement 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 convertir le résultat de la méthode clone.

0

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

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

Ceci devrait compiler - ajouter du code personnalisé au corps. Wikipedia était étonnamment utile sur celui-ci.

0

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

1

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 la méthode clone(), mais vous ne pouvez pas le faire.

D'une autre manière, vous ne pouvez pas passer outre une classe sur une interface: Méthode

Le clone() est toujours associé Whit la Object.class et non l'interface cloneable. Vous pouvez simplement le remplacer par un autre objet, pas dans une interface.

1

En ajoutant à la réponse de Sean Reilly, ceci devrait résoudre votre problème, et est plus sûr de type. Il compile et fonctionne très 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 ne pouvais pas le tester avec Java 5 parce que je ne l'ai pas installé, mais je suppose que cela fonctionnerait bien.

+0

Vous avez raison. Jolie petite astuce! Et comme vous le pensiez, cela fonctionnera très bien dans Java 5. –

0

CloningExample public class 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(); 

} 

}