Interface cloneable obrigatória em Java
-
04-07-2019 - |
Pergunta
Estou tendo um pequeno problema em Java. Eu tenho uma interface chamada modificáveis. Objetos implementar essa interface são modificáveis.
Eu também tenho uma classe ModifyCommand (com o padrão de comando) que recebem dois objetos modificáveis. (Para trocá-los em uma lista mais adiante - que não é a minha pergunta, eu projetei essa solução já)
A classe ModifyCommand começa por fazer clones dos objetos modificáveis. Logicamente, eu fiz a minha interface modificável estende Cloneable. A interface, em seguida, define um método clone () que suas classes de execução devem redefinir.
Então, em ModifyCommand, eu posso fazer: firstModifiableObject.clone (). Minha lógica é que as classes que implementam Modifiable terá que redefinir o método clone do objeto, como eles serão Cloneable (que é o que eu quero fazer).
A coisa é, quando eu definir classes implementos modificáveis ??e eu quero substituir clone (), ele não vai me deixar, afirmando que o método clone () das peles classe de objeto a de modificáveis.
O que devo fazer? Tenho a impressão de que "eu estou fazendo errado" ...
Obrigado,
Guillaume.
Edit: ele acha que eu vou esquecer a coisa clone (). Vou quer a) assumir que o objeto passado para o objeto modificável (implementação da interface) já é clonado ou b) fazer um outro método chamado, por exemplo, copiar (), que, basicamente, fazer uma deep-cópia do objeto modificável ( ou talvez a solução genérico vai funcionar ...).
Solução
Se você estiver usando java 1.5 ou superior, você pode obter o comportamento desejado e remover lançando desta forma:
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
}
}
Desde Foo estende Object, isto satisfaz ainda o contrato original da classe Object. Código que não refinar o método clone () corretamente não irá compilar, por causa das restrições adicionais impostas pela interface modificável. Como um bônus, chamar código não tem que converter o resultado do método clone.
Outras dicas
Você não precisa redefinir o método clone na interface modificável.
Verifique a documentação: http: / /java.sun.com/j2se/1.4.2/docs/api/java/lang/Cloneable.html
Eu entendo que você está tentando forçar todos a método clone override (), mas você não pode fazê-lo.
De outra forma, você não pode substituir uma classe em uma interface:
O método clone () está sempre associada a Whit Object.class e não a interface clonável. Você só pode substituí-lo em um outro objeto, não em uma interface.
Somando-se a resposta de Sean Reilly, este deve resolver o seu problema, e é mais tipo seguro. Ele compila e executa bem comigo em 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();
}
}
Eu não poderia testá-lo com Java 5, porque eu não tê-lo instalado, mas eu acho que iria funcionar bem.
Você definir a assinatura exatamente como no objeto?
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
Isso deve compilar - código personalizado add para o corpo. Wikipedia foi surpreendentemente útil em um presente.
O que a sua assinatura do método para o seu olhar de método de clone como? Para que ele coincidir com a interface clonable ele teria que retornar um objeto. Se você está declarando-lo como retornando um Modifiable seguida, que poderia ser o problema.
classe pública CloningExample implementos 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();
}
}