yerine copy constructor ile doğru bir şekilde kopyalamak için doğru yolu Object.clone kullanarak bir derin kopya gerçekleştiren bir kod var, ancak daha "kabul edilebilir" bir kopya oluşturucu tekniği kullanarak yeniden yazmaya çalışıyorum. Aşağıda, yapmaya çalıştığım şeyin iki basit örneği, ilk klon kullanımı ve ikincisi bir kopya kurucuyu kullanarak.Object.clone
Derin kopya kullanarak klon
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());
}
}
}
Derin kopya kullanarak kopya yapıcısı
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());
}
}
}
Benim ilginç bulduğum olduğunu Java klonlama kötülükleri hakkında tüm ifadesine rağmen, Klonlama alternatifi daha az kod ve daha az döküm gerektirir (bu durumda, en azından).
Kopya oluşturucu alternatifiyle ilgili geri bildirimleri takdir ediyorum. Bunu başka bir şekilde yapar mısın? Teşekkürler.
Person.deepCopy'yi unutmak veya güncelleyememek, karşılaştırmaya göre sorun değil. Yani, klon alternatifi ile çok benzer sorunlarla karşılaşabilirsiniz. Örneğin, bir kişi yeni bir "sınıf Yöneticisi Kişiyi uzatır" yaratırsa, Yönetici.clone'u uygulamayı hatırlamak zorunda kalacaktır (alandaki bir kopya kopyayı derin bir kopya yapmadığı varsayılarak). Person.deepCopy'yi güncelleyememek, alt sınıfta geçersiz kılarak ele alınabilir. Ve evet, bunu yapmayı hatırlamak zorundasınız, ama yine aynı klon alternatifi ile aynı sorun. – vocaro