Tengo un código que realiza una copia profunda usando Object.clone, pero estoy tratando de reescribirlo utilizando la técnica de creación de copia más "aceptable". A continuación hay dos ejemplos simples de lo que estoy tratando de hacer, el primero usando clon y el segundo usando un constructor de copia.Forma correcta de copiar en profundidad con el constructor de copia en lugar de Object.clone
copia profunda usando clon
import java.util.*;
abstract class Person implements Cloneable {
String name;
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
class Teacher extends Person implements Cloneable {
int courses;
public String toString() { return name + ": courses=" + courses; }
}
class Student extends Person implements Cloneable {
double gpa;
public String toString() { return name + ": gpa=" + gpa; }
}
public class DeepCopy_Clone {
private static List<Person> deepCopy(List<Person> people) throws CloneNotSupportedException {
List<Person> copy = new ArrayList<Person>();
for (Person person : people) {
copy.add((Person)person.clone());
}
return copy;
}
public static void main(String[] args) throws CloneNotSupportedException {
ArrayList<Person> people = new ArrayList<Person>();
Teacher teacher = new Teacher();
teacher.name = "Teacher";
teacher.courses = 5;
people.add(teacher);
Student student = new Student();
student.name = "Student";
student.gpa = 4.0;
people.add(student);
List<Person> peopleCopy = deepCopy(people);
// Invalidate the original data to prove a deep copy occurred
teacher.name = null;
teacher.courses = -1;
student.name = null;
student.gpa = -1;
for (Person person : peopleCopy) {
System.out.println(person.toString());
}
}
}
copia profunda usando constructor de copia
import java.util.*;
abstract class Person {
String name;
public Person() {}
public Person(Person other) {
this.name = other.name;
}
public Person deepCopy() {
if (this instanceof Teacher) {
return new Teacher((Teacher)this);
} else if (this instanceof Student) {
return new Student((Student)this);
}
throw new Error("Unknown type of person");
}
}
class Teacher extends Person {
int courses;
public Teacher() {}
public Teacher(Teacher other) {
super(other);
this.courses = other.courses;
}
public String toString() { return name + ": courses=" + courses; }
}
class Student extends Person {
double gpa;
public Student() {}
public Student(Student other) {
super(other);
this.gpa = other.gpa;
}
public String toString() { return name + ": gpa=" + gpa; }
}
public class DeepCopy_ConstructorAlternative {
private static List<Person> deepCopy(List<Person> people) {
List<Person> copy = new ArrayList<Person>();
for (Person person : people) {
copy.add(person.deepCopy());
}
return copy;
}
public static void main(String[] args) {
ArrayList<Person> people = new ArrayList<Person>();
Teacher teacher = new Teacher();
teacher.name = "Teacher";
teacher.courses = 5;
people.add(teacher);
Student student = new Student();
student.name = "Student";
student.gpa = 4.0;
people.add(student);
List<Person> peopleCopy = deepCopy(people);
// Invalidate the original data to prove a deep copy occurred
teacher.name = null;
teacher.courses = -1;
student.name = null;
student.gpa = -1;
for (Person person : peopleCopy) {
System.out.println(person.toString());
}
}
}
Lo que me parece interesante es que a pesar de todo lo dicho sobre los males de la clonación en Java, el la alternativa de clon requiere menos código y menos lanzamientos (en este caso particular, al menos).
Agradecería los comentarios sobre la alternativa del constructor de copias. ¿Lo harías de manera diferente? Gracias.
Olvidar o no poder actualizar Person.deepCopy no son problemas en comparación. Es decir, puede enfrentar problemas muy similares con la alternativa de clonación. Por ejemplo, si alguien crea un nuevo "administrador de clase extends Persona", deberá recordar implementar Administrator.clone (suponiendo que una copia de campo por campo no realiza una copia profunda). No poder actualizar Person.deepCopy puede manejarse sobrescribiéndolo en la subclase. Y sí, debes recordar hacer esto, pero nuevamente ese es el mismo problema con la alternativa de clonación. – vocaro