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 , desc.pointID);
}
}
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 показан соответствующий вывод.
Рис . 7.8. Метод MemberwiseClone() возвращает поверхностную копию объекта
Для того чтобы метод Clone() возвращал полные копии внутренних ссылочных типов, нужно "научить" возвращаемый методом MemberwiseClone() объект учитывать текущее имя объекта Point (тип System.Guid является структурой, так что на самом деле копируются числовые данные). Вот одна из возможных реализаций.
// Мы должны учесть наличие члена PointDescription.
public object Clone() {
Point newPoint = (Point)this.MemberwiseClone();
PointDescription currentDesc = new PointDescription();
сurrentDesc.petName = this.desc.petName;
newPoint.desc = currentDesc;
return newPoint;
}
Если выполнить приложение теперь, то вы увидите (рис. 7.9), что возвращенный методом Clone() объект Point действительно копирует внутренние ссылочные члены-переменные типа (обратите внимание на то, что здесь p3 и p4 имеют свои уникальные имена).
Итак, в том случае, когда класс или структура содержит только типы, характеризуемые значениями, лучше реализовать метод Clone(), использующий MemberwiseClone(). Однако в том случае, когда пользовательский тип содержит ссылочные типы, вы должны создать новый тип, принимающий во внимание все члены-переменные ссылочного типа.
Рис. 7.9. Здесь получена полная копия объекта
Исходный код.Проект CloneablePoint размещен в подкаталоге, соответствующем главе 7.
Создание сравнимых объектов (IComparable)
Интерфейс System.IComparable определяет поведение, позволяющее сортировать объекты по заданному ключу. Вот формальное определение.
// Этот интерфейс позволяет объекту указать его связь
// с другими подобными объектами.
public interface IComparable {
int CompareTo(object o);
}
Предположим теперь, что класс Car поддерживает некоторый внутренний идентификатор (представленный целым числом, хранимым в переменной carID), значение которого можно устанавливать с помощью параметра конструктора и изменять с помощью нового свойства ID. Ниже показана соответствующая модификация типа Car.
public class Car {
…
private int carID;
public int ID {
get { return carID; }
set { carID = value; }
}
public Car(string name, int currSp, int id) {
currSpeed = currSp;
petName = name;
carID = id;
}
…
}
Пользователи объекта могут создать массив типов Car так.
static void Main(string[] args) {
// Создание массива типов Car.
Car[] myAutos = new Car[5];
myAutos[0] = new Car("Rusty", 80, 1);
myAutos[1] = new Car("Mary" , 40, 234);
myAutos[2] = new Car("Viper", 40, 34);
myAutos[3] = new Car("Mel", 40, 4);
myAutos[4] = new Car("Chucky", 40, 5);
}
Вспомним, что класс System.Array определяет статический метод Sort(). Вызвав этот метод для массива встроенных типов (int, short, string и т.д.), можно отсортировать элементы в массиве в числовом или алфавитном порядке, поскольку встроенные типы данных реализуют IComparable. Но что произойдет в том случае, когда методу Sort() будет передан массив типов Car, как показано ниже?
Читать дальше