Главная

Популярная публикация

Научная публикация

Случайная публикация

Обратная связь

ТОР 5 статей:

Методические подходы к анализу финансового состояния предприятия

Проблема периодизации русской литературы ХХ века. Краткая характеристика второй половины ХХ века

Ценовые и неценовые факторы

Характеристика шлифовальных кругов и ее маркировка

Служебные части речи. Предлог. Союз. Частицы

КАТЕГОРИИ:






Клонирование и интерфейс ICloneable




При ссылочном присваивании x = y, где x и y - объекты класса T, как уже много раз говорилось, происходит присваивание ссылок. Если до присваивания ссылка y была связана с объектом в динамической памяти, то после присваивания x будет ссылаться на этот же объект. С самим объектом ничего не происходит, никакая копия этого объекта не создается. Иногда требуется создать копию объекта, так, чтобы x и y ссылались на разные объекты.

 

Клонированием называется процесс создания копии объекта, а копия объекта называется клоном. Различают два типа клонирования: поверхностное (shallow) и глубокое (deep). При поверхностном клонировании копируется только один объект, копию которого необходимо создать. Все значимые поля клона получают значения, совпадающие со значениями полей объекта; все ссылочные поля клона являются ссылками на те же объекты, на которые ссылается и сам объект.

При глубоком клонировании копируется вся совокупность объектов, связанных взаимными ссылками. Представьте себе мир объектов, описывающих людей. У этих объектов могут быть ссылки на детей и родителей, учителей и учеников, друзей и родственников. В текущий момент может существовать большое число таких объектов, связанных взаимными ссылками. Достаточно выбрать один из них в качестве корня, и при его клонировании воссоздастся копия существующей структуры объектов.

Глубокое клонирование требует рекурсивной процедуры обхода существующей структуры объектов, тщательно отработанной во избежание проблемы зацикливания. В общем случае, когда есть несколько классов, являющихся взаимными клиентами, глубокое клонирование требует наличия в каждом классе рекурсивной процедуры. Эти процедуры взаимно вызывают друг друга. Хорошим упражнением является создание проекта, реализующего глубокое клонирование для ситуации, когда объекты разных классов связаны взаимными ссылками.

Поверхностное клонирование можно выполнить достаточно просто, поскольку оно автоматически поддерживается для всех классов, в том числе, создаваемых программистом. Для создания поверхностного клона достаточно вызвать метод MemberwiseClone, наследуемый от прародителя object. Единственное, что нужно помнить: этот метод защищен, он не может быть вызван непосредственно клиентом класса. Если класс хочет обеспечить возможность создания клона клиентами класса, ему необходимо в классе создать метод, представляющий собой обертку метода MemberwiseClone.

Давайте обеспечим эту возможность для класса Person, создав в нем соответствующий метод:

public Person StandartClone()

{

Person p = (Person)this.MemberwiseClone();

return(p);

}

 

Теперь клиенты класса могут легко создавать поверхностные клоны. Вот пример:

public void TestStandartClone()

{

Person mother = new Person("Петрова Анна");

Person daughter = new Person("Петрова Ольга");

Person son = new Person("Петров Игорь");

mother[0] = daughter;

mother[1] = son;

Person mother_clone = mother.StandartClone();

Console.WriteLine("Дети матери: {0}",mother.Fam);

Console.WriteLine (mother[0].Fam);

Console.WriteLine (mother[1].Fam);

Console.WriteLine("Дети клона: {0}",mother_clone.Fam);

Console.WriteLine (mother_clone[0].Fam);

Console.WriteLine (mother_clone[1].Fam);

}

При создании клона будет создана копия только одного объекта mother. Обратите внимание: при работе с полем children, задающим детей, используется индексатор класса Person, выполняющий индексацию по этому полю. Вот как выглядят результаты работы теста.

Рис. 5.7. Поверхностное клонирование

Если стандартное поверхностное клонирование нас не устраивает, то класс можно объявить наследником интерфейса ICloneable и реализовать метод Clone - единственный метод этого интерфейса. В нем можно реализовать полное глубокое клонирование или подходящую для данного случая модификацию.

Давайте расширим класс Person, сделав его наследником интерфейса ICloneable. Реализация метода Clone будет отличаться от стандартной реализации тем, что к имени объекта - полю Fam - будет приписываться слово " clone ". Вот как выглядит этот метод:

public object Clone()

{

Person clone = (Person)this.MemberwiseClone();

clone.fam = "clone_" + fam;

return clone;

}

Эта реализация является слегка модифицированной версией стандартного поверхностного клонирования. Я добавил несколько строчек в тестирующую процедуру для проверки работы этой версии клона:

Person mother_clone2 = (Person)mother.Clone();

Console.WriteLine("Дети клона_2: {0}",mother_clone2.Fam);

Console.WriteLine (mother_clone2[0].Fam);

Console.WriteLine (mother_clone2[1].Fam);

Все работает должным образом.






Не нашли, что искали? Воспользуйтесь поиском:

vikidalka.ru - 2015-2024 год. Все права принадлежат их авторам! Нарушение авторских прав | Нарушение персональных данных