// Обратите внимание, Clone() возвращает объект общего типа.
// Для получении производного типа используйте явное преобразование.
Point р3 = new Point(100, 100);
Point р4 = (Point)р3.Clone();
// Изменение p4.х (это не изменит р3.х).
р4.х = 0;
// Вывод объектов.
Console.WriteLine(р3);
Console.WriteLine(p4);
}
Текущая реализация Point решает все поставленные задачи, но вы можете немного усовершенствовать процесс. Введу того, что тип Point не содержит переменных ссылочного типа, можно упростить реализацию метода Clone(), как показано ниже.
public object Clone() {
// Скопировать все поля Point "почленно"
return this.MemberwiseClone();
}
При наличии в Point членов-переменных ссылочного типа метод MemberwiseClone() скопирует ссылки на соответствующие объекты (т.е. выполнит
Пример клонирования
Предположим, что класс Point содержит член ссылочного типа с именем PointDescription, обеспечивающий поддержку "понятного" имени объекта Point и его идентификационного номера в виде System.Guid (еcли у вас нет опыта применения COM, знайте, что GUID – глобально уникальный идентификатор – это статистически уникальное 128-разрядное значение). Вот соответствующая реализация.
// Этот класс описывает точку.
public class PointDescription {
// Открыты для простоты.
public string petName;
public Guid pointID;
public PointDescription() {
this.petName = "Без имени";
pointID = Guid.NewGuid();
}
}
При этом для учета новых элементов состояния в самом классе Point следует изменить метод ToString(), а также операторы определения и создания ссылочного типа PointDescription. Чтобы позволить "внешнему миру" указать имя для Point, можно также модифицировать аргументы, передаваемые перегруженному конструктору.
public class Point: ICloneable {
public int x, y;
public PointDescription desc = new PointDescription();
public Point(){}
public Point (int x, int y) {
this.x = x;
this.у = у;
}
public Point(int x, int y, string petname) {
this.x = x;
this.у = у;
desc.petName = petname;
}
public object Clone() { return this.MemberwiseClone(); }
public override string ToString() {
return string.Format("X = {0}; Y = {1}; Имя = (2};\nID = {3}\n", x, y, desc.petName
}
}
He забудьте о том. что вы еще не обновили метод Clone(). Поэтому при запросе клонирования объекта пользователем с помощью данной реализации все равно будет получена поверхностная ("почленная") копия. Для примера предположим, что мы обновили метод Main() так, как показано ниже.
static void Main(string[] args) {
Console.WriteLine("***** Забавы с ICloneable *****\n");
Console.WriteLine("Клонирован р3, новый Point сохранен в р4");
Point p3 = new Point(100, 100, "Jane");
Point p4 = (Point)p3.Clone();
Console.WriteLine("До модификации:");
Console.WriteLine("р3: {0}", р3);
Console.WriteLine("p4: {0}", p4);
p4.desc.petName = "Мистер X";
p4.x = 9;
Console.WriteLine("Изменены p4.desc.petName и р4.х");
Console.WriteLine("После модификации: ");
Console.WriteLine("p3: {0}", р3);
Console.WriteLine("p4: {0}", p4)
}
На рис. 7.8 показан соответствующий вывод.
Рис