Главная страница Библиотека (скачать книги) Скачать софт Введение в программирование Стандарты для C++ Уроки по C# Уроки по Python HTML Веб-дизайн Ассемблер в среде Windows ActiveX Javascript Общее о Линукс Линукс - подробно Линукс - новое Delphi Паскаль для начинающих Турбопаскаль Новости Партнеры Наши предложения Архив новостей |
Практический пример. Поверхностное и глубокое копирование
В этом разделе мы рассмотрим проблему копирования объектов ссылочных типов. Дело в том, что при копировании структурных типов копируются сами объекты, а при копировании ссылочных - ссылки (в терминах C++ указатели). Проблему частично помогает решить защищенный метод MemberwiseClone() класса Object, который неявно наследуют все классы. using System; namespace CSharpApplication.CloneExample { // Класс студент class Student { // Имя string FirstName; // Фамилия string LastName; // Адрес string Address; // Телефон string Phone; // Дата рождения DateTime BirthDay; // Поверхностное копирование объекта public Student Clone() { // Вызываем функцию базового класса (Object) // для поверхностного копирования объекта return (Student)MemberwiseClone(); } // Ввод данных public void Input() { Console.WriteLine("*****Ввод данных о студенте:******"); Console.Write("Имя: "); FirstName = Console.ReadLine(); Console.Write("Фамилия: "); LastName = Console.ReadLine(); Console.Write("Адрес: "); Address = Console.ReadLine(); Console.Write("Телефон: "); Phone = Console.ReadLine(); Console.Write("Дата рождения: "); try { BirthDay = Convert.ToDateTime(Console.ReadLine()); } catch { Console.WriteLine("Ошибка ввода, используем текущую дату"); BirthDay = DateTime.Now; } Console.WriteLine("**********************************"); } // Вывод данных public void Print() { Console.WriteLine("*****Вывод данных о студенте:*****"); Console.WriteLine("Имя: {0}", FirstName); Console.WriteLine("Фамилия: {0}", LastName); Console.WriteLine("Адрес: {0}", Address); Console.WriteLine("Телефон: {0}", Phone); Console.WriteLine("Дата рождения: {0}.{1}.{2}", BirthDay.Day, BirthDay.Month, BirthDay.Year); Console.WriteLine("**********************************"); } } // Класс Group class Group : ICloneable { // Название группы string GroupName; // Массив студентов Student [] st; // Конструктор, получающий название группы и количество студентов public Group(string gn, int n) { GroupName = gn; // По умолчанию в группе 10 студентов if(n <= 0 || n > 10) n = 10; st = new Student[n]; // Создаем студентов for(int i = 0; i < n; i++) st[i] = new Student(); } // Аналог конструктора копирования public Group(Group gr) { // Создаем массив студентов st = new Student[gr.st.Length]; // Передираем название группы GroupName = gr.GroupName; // Передираем каждого индивидуума for(int i = 0; i < gr.st.Length; i++) st[i] = gr.st[i].Clone(); } // Заполняем группу public void Input() { for(int i = 0; i < st.Length; i++) { Console.WriteLine("{0}.", i + 1); st[i].Input(); } } // Изменение данных конкретного студента public void InputAt(int n) { if(st == null || n >= st.Length || n < 0) return; st[n].Input(); } // Вывод списка группы public void Print() { Console.WriteLine("Группа {0}:", GroupName); for(int i = 0; i < st.Length; i++) { Console.WriteLine("{0}.", i + 1); st[i].Print(); } } // Вывод информации о конкретном студенте public void PrintAt(int n) { if(st == null || n >= st.Length || n < 0) return; st[n].Print(); } // Получение имени группы public string GetGroupName() { return GroupName; } // Изменение имени группы public void SetGroupName(string gn) { GroupName = gn; } // Поверхностное копирование public new object MemberwiseClone() { // Функция класса Object return base.MemberwiseClone(); } // "Глубокое" копирование, // реализация функции из интерфейса IClonable public object Clone() { // Создание новой группы Group gr = new Group(GroupName, st.Length); // Передираем каждого индивидуума for(int i = 0; i < st.Length; i++) gr.st[i] = st[i].Clone(); // Возврат независимой копии группы return gr; } } // Тестирование class Test { static void Main() { Group grcopy; // Группа из одного студента (для простоты ввода) Group gr = new Group("АС-951", 1); gr.Input(); gr.Print(); /************************************************************/ /* Копирование ссылок приводит к созданию двух ссылок /* на один и тот же объект /************************************************************/ grcopy = gr; grcopy.SetGroupName("АМ-951"); // Изменяем данные grcopy.InputAt(0); // Вывод (информация окажется одинаковой) Console.WriteLine(grcopy.GetGroupName()); grcopy.PrintAt(0); Console.WriteLine(gr.GetGroupName()); gr.PrintAt(0); /************************************************************/ /* Поверхностное копирование, название групп будут /* различны, но ссылки st у обоих объектов будут /* хранить одинаковые адреса /************************************************************/ grcopy = (Group)gr.MemberwiseClone(); grcopy.SetGroupName("АП-951"); // Изменяем данные grcopy.InputAt(0); // Вывод (информация о студенте окажется одинаковой) Console.WriteLine(grcopy.GetGroupName()); grcopy.PrintAt(0); Console.WriteLine(gr.GetGroupName()); gr.PrintAt(0); /************************************************************/ /* "Глубокое" копирование, мы получаем два независимых объекта /************************************************************/ grcopy = (Group)gr.Clone(); grcopy.SetGroupName("АТ-951"); // Изменяем данные grcopy.InputAt(0); // Вывод Console.WriteLine(grcopy.GetGroupName()); grcopy.PrintAt(0); Console.WriteLine(gr.GetGroupName()); gr.PrintAt(0); /************************************************************/ /* Аналог конструктора копирования /************************************************************/ Group gg = new Group(grcopy); grcopy.SetGroupName("АИ-951"); // Изменяем данные grcopy.InputAt(0); // Вывод Console.WriteLine(grcopy.GetGroupName()); grcopy.PrintAt(0); Console.WriteLine(gg.GetGroupName()); gg.PrintAt(0); } } } Более подробную информацию можно получить, изучив практические примеры, или заглянув в MSDN. Домашнее заданиеРазработать иерархию классов для рисования простых геометрических фигур (звездочками). необходимо обеспечить возможность отрисовки прямоугольников, треугольников, ромбов (все диагональные линии идут под углом 45 градусов). Оценивается качество и реализация модели. |
|
Библиотека программиста. 2009. |
|