Клонирование объектов (интерфейс ICIoneable)

Рис. 9.1. Клонирование объектов

Клонирование — это создание копии объекта. Копия объекта называется кло­ном. Как вам известно, при присваивании одного объекта ссылочного типа дру­гому копируется ссылка, а не сам объект (рис. 9.1, а). Если необходимо скопи­ровать в другую область памяти поля объекта, можно воспользоваться методом MemberwiseClone, который любой объект наследует от класса object. При этом объ­екты, на которые указывают поля объекта, в свою очередь являющиеся ссылка­ми, не копируются (рис. 9.1, 6). Это называется поверхностным клонированием.

Для создания полностью независимых объектов необходимо глубокое клонирова­ние, когда в памяти создается дубликат всего дерева объектов, то есть объектов, на которые ссылаются поля объекта, поля полей и т. д. (рис. 9.1, в). Алгоритм глубокого клонирования весьма сложен, поскольку требует рекурсивного обхода всех ссылок объекта и отслеживания циклических зависимостей. Объект, имеющий собственные алгоритмы клонирования, должен объявляться как наследник интерфейса ICloneable и переопределять его единственный метод Clone. В листинге 9.4 приведен пример создания поверхностной копии объекта класса Monster с помощью метода MemberwiseClone, а также реализован интерфейс ICloneable. В демонстрационных целях в имя клона объекта добавлено слово «Клон». Обратите внимание на то, что метод MemberwiseClone можно вызвать только из методов класса. Он не может быть вызван непосредственно, поскольку объявлен в классе object как защищенный (protected).

Листинг 9.4. Клонирование объектов

using System;

namespace ConsoleApplication1

{

class Monster: ICloneable

{

public Monster(int health, int ammo, string name)

{

this.health = health;

this.ammo = ammo;

this.name = name;

}

public Monster ShallowClone() // поверхностная копия

{

return (Monster)this.MemberwiseClone();

}

public object Clone() // пользовательская копия

{

return new Monster(this.health, this.ammo, "Клон " + this.name);

}

virtual public void Passport()

{

Console.WriteLine("Monster {0} \t health = {1} ammo = {2}",

name, health, ammo);

}

string name; int health, ammo;

}

class Class1

{

static void Main()

{

Monster Вася = new Monster(70, 80, "Вася");

Monster X = Вася;

Monster Y = Bacя.ShallowClone();

Monster Z = (Monster)Bacя.Clone();

}

}

}

Объект X ссылается на ту же область памяти, что и объект Вася. Следовательно, если мы внесем изменения в один из этих объектов, это отразится на другом. Объекты Y и Z, созданные путем клонирования, обладают собственными копия­ми значений полей и независимы от исходного объекта.


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: