Pregunta

Tengo un pequeño problema en Java. Tengo una interfaz llamada Modificable. Los objetos que implementan esta interfaz son modificables.

También tengo una clase ModifyCommand (con el patrón de Comando) que recibe dos objetos Modificables (para intercambiarlos en una lista más adelante, esa no es mi pregunta, ya diseñé esa solución).

La clase ModifyCommand comienza haciendo clones de los objetos modificables. Lógicamente, hice que mi interfaz modificable se extendiera a Cloneable. La interfaz luego define un método clone () que sus clases de implementación deben redefinir.

Luego, en ModifyCommand, puedo hacer: firstModifiableObject.clone (). Mi lógica es que las clases que implementan Modifiable tendrán que redefinir el método de clonación de Objeto, ya que serán Clonables (eso es lo que quiero hacer).

Lo importante es que, cuando defino las implementaciones de clases Modificables y quiero anular clone (), no me deja, indicando que el método clone () de la clase Object oculta el de Modifiable.

¿Qué debo hacer? Tengo la impresión de que " Lo estoy haciendo mal " ...

Gracias,

Guillaume.

Edit: creo que olvidaré el clon (). Supongo que a) el objeto pasado al objeto modificable (implementando la interfaz) ya está clonado o b) creará otro método llamado, por ejemplo, copy (), que básicamente haría una copia profunda del objeto modificable ( o tal vez la solución genérica funcione ...).

¿Fue útil?

Solución

Si está utilizando Java 1.5 o superior, puede obtener el comportamiento que desea y eliminar el envío de esta manera:

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

Dado que Foo extiende Object, esto aún satisface el contrato original de la clase Object. El código que no refina el método clone () correctamente no se compilará, debido a las restricciones adicionales impuestas por la interfaz modificable. Como beneficio adicional, el código de llamada no tiene que emitir el resultado del método de clonación.

Otros consejos

No es necesario redefinir el método de clonación en la interfaz Modificable.

Consulte la documentación: http: / /java.sun.com/j2se/1.4.2/docs/api/java/lang/Cloneable.html

Comprendo que intentas obligar a todos a anular el método de clonación (), pero no puedes hacerlo.

De otra manera, no puede anular una clase en una interfaz:

El método clone () siempre está asociado con Object.class y no con la interfaz clonable. Solo puede anularlo en otro objeto, no en una interfaz.

Agregando a la respuesta de Sean Reilly, esto debería resolver su problema y es más seguro. Se compila y funciona bien conmigo en 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();
    }
}

No pude probarlo con Java 5 porque no lo tengo instalado, pero creo que funcionará bien.

¿Definió la firma exactamente como está en el objeto?

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

Esto debería compilar: añada código personalizado al cuerpo. Wikipedia fue sorprendentemente útil en este caso.

¿Cómo se ve tu firma de método para tu método de clonación? Para que coincida con la interfaz Clonable tendría que devolver un Objeto. Si lo está declarando como que devuelve un Modificable, entonces ese podría ser el problema.

la clase pública CloningExample 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();

}

}

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top