2

给定一个树层次结构,假设它如下:

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,所以无法返回克隆的 Person,因此无法克隆 Person。

我想出的最佳答案是重载 Person 类中的 Clone() 方法以接收 Person,克隆并返回它。然后在 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
}     

当然,如果上述任何一个类都需要在其构造函数中构建任何逻辑,那么这个解决方案就毫无用处了。有什么想法可以实现更好的吗?

我认为这是一个更一般的问题的子问题,因此答案将非常适合大型超集。

4

1 回答 1

2

由于您的 Student 类从基类 (Person) 继承属性/字段,因此无需克隆 person 对象。

解决方案是不在抽象基类中实现 Clone() 方法,而是使其抽象并强制在继承自它的任何子类中实现。为了克隆,您可以简单地实例化 Student 类的新实例并使用克隆构造函数填充基本属性。看我的例子。我不确定这是否有任何帮助。

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;
        }
    }
于 2015-01-24T01:42:20.237 回答