Пример клонирования

Пример клонирования

Предположим, что класс 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}; ID = {3} ", x, y, desc.petName, desc.pointID);

 }

}

He забудьте о том. что вы еще не обновили метод Clone(). Поэтому при запросе клонирования объекта пользователем с помощью данной реализации все равно будет получена поверхностная ("почленная") копия. Для примера предположим, что мы обновили метод Main() так, как показано ниже.

static void Main(string[] args) {

 Console.WriteLine("***** Забавы с ICloneable ***** ");

 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.

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Форма операций клонирования и эквивалентности

Из книги Основы объектно-ориентированного программирования автора Мейер Бертран

Форма операций клонирования и эквивалентности Форма вызова подпрограмм clone и equal является стилевой особенностью, которая может вызвать удивление. На первый взгляд нотация:clone (x)equal (x, y)выглядит не слишком объектно-ориентированной. Догматичное следование принципу


Пример

Из книги UNIX: взаимодействие процессов автора Стивенс Уильям Ричард

Пример Вернемся к нашему примеру из листинга 9.2 и перепишем функции my_lock и my_unlock из листинга 9.1 так, чтобы воспользоваться блокировкой записей Posix. Текст этих функций приведен в листинге 9.3.Листинг 9.3. Блокировка записей fcntl по стандарту Posix//lock/lockfcntl.c1  #include


Пример

Из книги Стандарты программирования на С++. 101 правило и рекомендация автора Александреску Андрей

Пример Программа в листинге 14.5 определяет значения четырех ограничений, приведенных в табл. 14.1.Листинг 14.5. Определение системных ограничений на разделяемую память//svshm/limits.c1  #include "unpipc.h"2  #define MAX_NIDS 40963  int4  main(int argc, char **argv)5  {6   int i, j, shmid[MAX_NIDS];7   void *addr[MAX_NIDS];8   unsigned long


Пример

Из книги Искусство программирования на языке сценариев командной оболочки автора Купер Мендель

Пример Начнем описание интерфейса дверей с простого примера: клиент передает серверу длинное целое, а сервер возвращает клиенту квадрат этого значения тоже как длинное целое. В листинге 15.1[1] приведен текст программы-клиента (в этом примере мы опускаем множество деталей,


Пример

Из книги Вопросы истории: UNIX, Linux, BSD и другие автора Федорчук Алексей Викторович

Пример В качестве примера использования RPC перепишем листинги 15.1 и 15.2 для использования Sun RPC вместо дверей. Клиент вызывает процедуру сервера с аргументом типа long, а возвращаемое значение представляет собой квадрат аргумента. В листинге 16.1[1] приведен текст первого файла,


54. Избегайте срезки. Подумайте об использовании в базовом классе клонирования вместо копирования

Из книги автора

54. Избегайте срезки. Подумайте об использовании в базовом классе клонирования вместо копирования РезюмеСрезка объектов происходит автоматически, невидимо и может приводить к полному разрушению чудесного полиморфного дизайна. Подумайте о полном запрете копирующего


Пример 9-3. Еще один пример ограничения времени ожидания ввода от пользователя

Из книги автора

Пример 9-3. Еще один пример ограничения времени ожидания ввода от пользователя #!/bin/bash# timeout.sh# Автор: Stephane Chazelas,# дополнен автором документа.INTERVAL=5 # предел времени ожиданияtimedout_read() { timeout=$1 varname=$2 old_tty_settings=`stty -g` stty -icanon min 0 time ${timeout}0 eval read $varname # или просто read $varname


Пример 10-27. Простой пример сравнения строк

Из книги автора

Пример 10-27. Простой пример сравнения строк #!/bin/bash# match-string.sh: простое сравнение строкmatch_string (){ MATCH=0 NOMATCH=90 PARAMS=2 # Функция требует два входных аргумента. BAD_PARAMS=91 [ $# -eq $PARAMS ] || return $BAD_PARAMS case "$1" in "$2") return $MATCH;; * ) return $NOMATCH;; esac}a=oneb=twoc=threed=twomatch_string $a # неверное число


Пример 12-20. Пример форматирования списка файлов в каталоге

Из книги автора

Пример 12-20. Пример форматирования списка файлов в каталоге #!/bin/bash# За основу сценария взят пример "man column".(printf "PERMISSIONS LINKS OWNER GROUP SIZE DATE TIME PROG-NAME " ; ls -l | sed 1d) | column -t# Команда "sed 1d" удаляет первую строку, выводимую командой ls,#+ (для локали "С" это строка: "total N",#+ где "N" -- общее


Пример 12-45. Пример работы с m4

Из книги автора

Пример 12-45. Пример работы с m4 #!/bin/bash# m4.sh: Демонстрация некоторых возможносией макропроцессора m4# Строкиstring=abcdA01echo "len($string)" | m4 # 7echo "substr($string,4)" | m4 # A01echo "regexp($string,[0-1][0-1],&Z)" | m4 # 01Z# Арифметикаecho "incr(22)" | m4 # 23echo "eval(99 / 3)" | m4 #


Пример 24-2. Еще один пример проверки аргументов с помощью "И-списков"

Из книги автора

Пример 24-2. Еще один пример проверки аргументов с помощью "И-списков" #!/bin/bashARGS=1 # Ожидаемое число аргументов.E_BADARGS=65 # Код завершения, если число аргументов меньше ожидаемого.test $# -ne $ARGS && echo "Порядок использования: `basename $0` $ARGS аргумент(а)(ов)" && exit $E_BADARGS# Если


Пример 25-8. Пример реализации алгоритма Решето Эратосфена

Из книги автора

Пример 25-8. Пример реализации алгоритма Решето Эратосфена #!/bin/bash# sieve.sh# Решето Эратосфена# Очень старый алгоритм поиска простых чисел.# Этот сценарий выполняется во много раз медленнее# чем аналогичная программа на C.LOWER_LIMIT=1 # Начиная с 1.UPPER_LIMIT=1000 # До 1000.# (Вы можете