La clonación es un paradigma de programación básico. El hecho de que Java pueda haberlo implementado de manera deficiente de muchas maneras no disminuye en absoluto la necesidad de clonación. Y, es fácil implementar la clonación que funcionará como usted quiera que funcione, superficial, profunda, mixta, lo que sea. Incluso puede usar el nombre clon para la función y no implementar Cloneable si lo desea.
Supongamos que tengo las clases A, B y C, donde B y C se derivan de A. Si tengo una lista de objetos de tipo A como esta:
ArrayList<A> list1;
Ahora, esa lista puede contener objetos de tipo A, B o C. No sabe de qué tipo son los objetos. Entonces, no puede copiar la lista de esta manera:
ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
list2.add(new A(a));
}
Si el objeto es en realidad de tipo B o C, no obtendrá la copia correcta. ¿Y si A es abstracto? Ahora, algunas personas han sugerido esto:
ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
if(a instanceof A) {
list2.add(new A(a));
} else if(a instanceof B) {
list2.add(new B(a));
} else if(a instanceof C) {
list2.add(new C(a));
}
}
Esta es una muy, muy mala idea. ¿Qué pasa si agrega un nuevo tipo derivado? ¿Qué pasa si B o C están en otro paquete y no tiene acceso a ellos en esta clase?
Lo que le gustaría hacer es esto:
ArrayList<A> list2 = new ArrayList<A>();
for(A a : list1) {
list2.add(a.clone());
}
Mucha gente ha indicado por qué la implementación básica de Java del clon es problemática. Pero, se supera fácilmente de esta manera:
En clase A:
public A clone() {
return new A(this);
}
En clase B:
@Override
public B clone() {
return new B(this);
}
En clase C:
@Override
public C clone() {
return new C(this):
}
No estoy implementando Cloneable, solo uso el mismo nombre de función. Si no le gusta, asígnele otro nombre.