Interfaccia clonabile obbligatoria in Java


Sto avendo un piccolo problema in Java. Ho un'interfaccia chiamata Modificabile. Gli oggetti che implementano questa interfaccia sono modificabili.

Ho anche una classe ModifyCommand (con il modello di comando) che riceve due oggetti modificabili (per scambiarli in un elenco più avanti - non è la mia domanda, ho già progettato quella soluzione).

La classe ModifyCommand inizia creando cloni degli oggetti modificabili. Logicamente, ho reso la mia interfaccia modificabile si estende Clonabile. Il l'interfaccia definisce quindi un metodo clone () che le sue classi di implementazione devono ridefinire.

Quindi, in ModifyCommand, posso fare : firstModifiableObject.clone(). La mia logica è che le classi che implementano Modificabili dovranno ridefinire il metodo clone dall'Oggetto, poiché saranno Clonabili (è quello che voglio fare).

Il fatto è che quando definisco le classi implementa modificabili e voglio sovrascrivere clone (), non me lo consente, affermando che il metodo clone () dalla classe Object nasconde il uno da Modificabile.

Cosa devo fare? Ho l'impressione che "Lo sto facendo male"...

Grazie,

Guillaume.

Edit : penso che dimenticherò la cosa clone (). A) presumo che l'oggetto passato all'oggetto modificabile (implementando l'interfaccia) sia già clonato o b) crea un altro metodo chiamato, ad esempio, copy(), che fondamentalmente farebbe una copia profonda dell'oggetto modificabile (o forse la soluzione generica funzionerà...).

Author: Guillaume Gervais, 2008-10-27

6 answers

Se si utilizza java 1.5 o superiore, è possibile ottenere il comportamento desiderato e rimuovere il casting in questo modo:

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
    }
}

Poiché Foo estende l'oggetto, questo soddisfa ancora il contratto originale della classe Object. Il codice che non perfeziona correttamente il metodo clone() non verrà compilato, a causa dei vincoli aggiuntivi imposti dall'interfaccia modificabile. Come bonus, il codice di chiamata non deve lanciare il risultato del metodo clone.

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

Non è necessario ridefinire il metodo clone sull'interfaccia modificabile.

Controllare la documentazione: http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Cloneable.html

Capisco che stai cercando di forzare tutti a sovrascrivere il metodo clone(), ma non puoi farlo.

In un altro modo, non è possibile sovrascrivere una classe su un'interfaccia:

Il metodo clone() è sempre associato all'Oggetto.classe e non l'interfaccia clonabile. Puoi e basta sovrascriverlo su un altro oggetto, non in un'interfaccia.

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

Aggiungendo alla risposta di Sean Reilly, questo dovrebbe risolvere il tuo problema ed è più sicuro. Compila e funziona bene con me su 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();
    }
}

Non ho potuto testarlo con Java 5 perché non l'ho installato, ma immagino che funzionerebbe bene.

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

Hai definito la firma esattamente com'è nell'oggetto?

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

Questo dovrebbe compilare - aggiungere codice personalizzato al corpo. Wikipedia è stata sorprendentemente utile su questo.

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

Come appare la firma del metodo per il metodo clone? Affinché corrisponda all'interfaccia Clonabile, dovrebbe restituire un oggetto. Se lo stai dichiarando come restituendo un Modificabile, questo potrebbe essere il problema.

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

CloningExample classe pubblica implementa 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