如何在以抽象 class 为根的树层次结构中更正实现 ICloneable?
How to correct implement ICloneable in a tree hierarchy rooted by an abstract class?
给定一个树层次结构,假设它是这样的:
abstract class Person : ICloneable
...
sealed class Student : Person
...
我想实现ICloneable接口。在 Student.Clone 方法中,我希望做类似的事情:
{
Student clonedStudent = base.Clone() as Student;
clonedStudent.x1 = this.x1;
return clonedStudent
}
因为 Person 是抽象的我不能在 Person.Clone() 方法中创建一个 Person,所以我不能 return 一个克隆的 Person,所以我不能克隆一个 Person。
我想出的最佳答案是重载 Person class 中的 Clone() 方法以接收一个 Person,克隆并 return 它。然后在 Student.Clone 实现中调用此重载以克隆此人的相关字段。
像这样:
//In the Person class:
public abstract object Clone();
protected Person Clone(Person clonedPerson)
{
// Clone all person's fields
return clonedPerson:
}
//In the Student class:
public override object Clone()
{
Student clonedStudent = base.Clone(new Student()) as Student;
// Clone all student's fields
return clonedStudent
}
当然,如果上述任何 class 需要在其构造函数中构建任何逻辑,则此解决方案毫无用处。有实施更好方案的想法吗?
我认为这是一个更一般问题的子问题,所以答案将非常适合一个大的超集。
由于您的 Student class 从基础 class(Person)继承了 properties/fields,因此没有必要克隆 person 对象。
解决方案是不在抽象基 class 中实现 Clone() 方法,而是将其抽象化并强制在从它继承的任何子 class 中实现。为了克隆,您可以简单地实例化 Student class 的新实例并使用克隆构造函数填充基本属性。看我的例子。我不确定这是否有任何帮助。
class Program
{
static void Main(string[] args)
{
Student studentA = new Student(1000, "Defense Against the Dark Arts", "Harry", "Potter", 25);
Student studentB = (Student)studentA.Clone();
}
}
public abstract class Person : ICloneable
{
public string FirstName { get; set; }
public string Surname { get; set; }
private int SomePrivateVariable { get; set; }
public Person()
{
}
public Person(string firstName, string surname, int privateVariableDefault)
{
this.FirstName = firstName;
this.Surname = surname;
this.SomePrivateVariable = privateVariableDefault;
}
public Person(Person original)
{
this.FirstName = original.FirstName;
this.Surname = original.Surname;
this.SomePrivateVariable = original.SomePrivateVariable;
}
public abstract object Clone();
}
public sealed class Student : Person
{
public int StudentId { get; set; }
public string CourseTitle { get; set; }
public Student()
{
}
//Constructor with all the fields, passed down to the base class
public Student(int studentId, string courseTitle, string firstName, string surname, int baseVariableDefault)
: base(firstName, surname, baseVariableDefault)
{
this.StudentId = studentId;
this.CourseTitle = courseTitle;
}
//A clone constructor which takes an object of the same type and populates internal
//and base properties during construction
public Student(Student original)
: base(original)
{
this.FirstName = original.FirstName;
this.Surname = original.Surname;
this.StudentId = original.StudentId;
this.CourseTitle = original.CourseTitle;
}
public override object Clone()
{
Student clone = new Student(this);
return clone;
}
}
给定一个树层次结构,假设它是这样的:
abstract class Person : ICloneable
...
sealed class Student : Person
...
我想实现ICloneable接口。在 Student.Clone 方法中,我希望做类似的事情:
{
Student clonedStudent = base.Clone() as Student;
clonedStudent.x1 = this.x1;
return clonedStudent
}
因为 Person 是抽象的我不能在 Person.Clone() 方法中创建一个 Person,所以我不能 return 一个克隆的 Person,所以我不能克隆一个 Person。
我想出的最佳答案是重载 Person class 中的 Clone() 方法以接收一个 Person,克隆并 return 它。然后在 Student.Clone 实现中调用此重载以克隆此人的相关字段。 像这样:
//In the Person class:
public abstract object Clone();
protected Person Clone(Person clonedPerson)
{
// Clone all person's fields
return clonedPerson:
}
//In the Student class:
public override object Clone()
{
Student clonedStudent = base.Clone(new Student()) as Student;
// Clone all student's fields
return clonedStudent
}
当然,如果上述任何 class 需要在其构造函数中构建任何逻辑,则此解决方案毫无用处。有实施更好方案的想法吗?
我认为这是一个更一般问题的子问题,所以答案将非常适合一个大的超集。
由于您的 Student class 从基础 class(Person)继承了 properties/fields,因此没有必要克隆 person 对象。
解决方案是不在抽象基 class 中实现 Clone() 方法,而是将其抽象化并强制在从它继承的任何子 class 中实现。为了克隆,您可以简单地实例化 Student class 的新实例并使用克隆构造函数填充基本属性。看我的例子。我不确定这是否有任何帮助。
class Program
{
static void Main(string[] args)
{
Student studentA = new Student(1000, "Defense Against the Dark Arts", "Harry", "Potter", 25);
Student studentB = (Student)studentA.Clone();
}
}
public abstract class Person : ICloneable
{
public string FirstName { get; set; }
public string Surname { get; set; }
private int SomePrivateVariable { get; set; }
public Person()
{
}
public Person(string firstName, string surname, int privateVariableDefault)
{
this.FirstName = firstName;
this.Surname = surname;
this.SomePrivateVariable = privateVariableDefault;
}
public Person(Person original)
{
this.FirstName = original.FirstName;
this.Surname = original.Surname;
this.SomePrivateVariable = original.SomePrivateVariable;
}
public abstract object Clone();
}
public sealed class Student : Person
{
public int StudentId { get; set; }
public string CourseTitle { get; set; }
public Student()
{
}
//Constructor with all the fields, passed down to the base class
public Student(int studentId, string courseTitle, string firstName, string surname, int baseVariableDefault)
: base(firstName, surname, baseVariableDefault)
{
this.StudentId = studentId;
this.CourseTitle = courseTitle;
}
//A clone constructor which takes an object of the same type and populates internal
//and base properties during construction
public Student(Student original)
: base(original)
{
this.FirstName = original.FirstName;
this.Surname = original.Surname;
this.StudentId = original.StudentId;
this.CourseTitle = original.CourseTitle;
}
public override object Clone()
{
Student clone = new Student(this);
return clone;
}
}