Лабораторная работа 2 Наследование. Исключения. Интерфейсы. Итераторы и блоки итераторов
В классе Person из лабораторной работы 1 и в классах, дополнительно указанных в вариантах, надо
• переопределить (override) виртуальный метод bool Equals (object obj);
• определить операции == и != ;
• переопределить виртуальный метод int GetHashCode();
Реализация виртуального метода bool Equals (object obj) в классе System.Object определяет равенство объектов как равенство ссылок на объекты. Некоторые классы из базовой библиотеки BCL переопределяют метод Equals(). В классе System.String этот метод переопределен так, что равными считаются строки, которые совпадают посимвольно. Реализация метода Equals() в структурном типе DateTime равенство объектов DateTime определяет как равенство значений.
В лабораторной работе требуется переопределить метод Equals так, чтобы объекты считались равными, если равны все данные объектов. Для класса Person это означает, что равны даты рождения и посимвольно совпадают строки с именем и фамилией.
Определение операций == и != должно быть согласовано с переопределенным методом Equals, т.е. критерии, по которым проверяется равенство объектов в методе Equals, должны использоваться и при проверке равенства объектов в операциях == и !=.
Переопределение виртуального метода int GetHashCode() также должно быть согласовано с операциями == и !=. Виртуальный метод GetHashCode() используется некоторыми классами базовой библиотеки, например, коллекциями-словарями. Классы базовой библиотеки, вызывающие метод GetHashCode() из пользовательского типа, предполагают, что равным объектам отвечают равные значения хэш-кодов. Поэтому в случае, когда под равенством объектов понимается совпадение данных (а не ссылок), реализация метода GetHashCode() должна для объектов с совпадающими данными возвращать равные значения хэш-кодов.
В классах, указанных в вариантах лабораторной работы, требуется определить метод object DeepCopy() для создания полной копии объекта. Определенные в некоторых классах базовой библиотеки методы Clone() и Copy() создают ограниченную (shallow) копию объекта – при копировании объекта копии создаются только для полей структурных типов, для полей ссылочных типов копируются только ссылки. В результате в ограниченной копии объекта поля-ссылки указывают на те же объекты, что и в исходном объекте.
Метод DeepCopy() должен создать полные копии всех объектов, ссылки на которые содержат поля типа. После создания полная копия не зависит от исходного объекта - изменение любого поля или свойства исходного объекта не должно приводить к изменению копии.
При реализации метода DeepCopy() в классе, который имеет поле типа System.Collections.ArrayList, следует иметь в виду, что определенные в классе ArrayList конструктор ArrayList(ICollection) и метод Clone() при создании копии коллекции, состоящей из элементов ссылочных типов, копируют только ссылки.
Метод DeepCopy() должен создать как копии элементов коллекции ArrayList, так и полные копии объектов, на которые ссылаются элементы коллекции. Для типов, содержащих коллекции, реализация метода DeepCopy() упрощается, если в типах элементов коллекций также определить метод DeepCopy().
Вариант 3. Требования к программе Определить интерфейс
interface INameAndCopy { string Name { get; set;} object DeepCopy(); } Определить новые версии классов Person, Paper и ResearchTeam из лабораторной работы 1. Класс ResearchTeam определить как производный от класса Team. В классы Team и ResearchTeam добавить реализацию интерфейса INameAndCopy. В классе Paper определить виртуальный метод object DeepCopy(). В новой версии класса Person дополнительно • переопределить метод virtial bool Equals (object obj) и определить операции == и != так, чтобы равенство объектов типа Person трактовалось как совпадение всех данных объектов, а не ссылок на объекты Person; • переопределить виртуальный метод int GetHashCode(); • определить виртуальный метод object DeepCopy(). Определить класс Team. Класс Team имеет • защищенное (protected) поле типа string с названием организации; • защищенное поле типа int – регистрационный номер. В классе Team определить: • конструктор с параметрами типа string и int для инициализации полей класса; • конструктор без параметров для инициализации по умолчанию; • свойство типа string для доступа к полю с названием организации; • свойство типа int для доступа к полю с номером регистрации; в методе set бросить исключение, если присваиваемое значение меньше или равно 0; при создании объекта-исключения использовать один из определенных в библиотеке CLR классов-исключений, инициализировать объект-исключение с помощью конструктора с параметром типа string. В классе Team • определить виртуальный метод object DeepCopy(); • реализовать интерфейс INameAndCopy. В классе Team переопределить (override): • виртуальный метод virtial bool Equals (object obj) и определить операции == и != так, чтобы равенство объектов типа Team трактовалось как совпадение всех данных объектов, а не ссылок на объекты Team; • виртуальный метод int GetHashCode(); • виртуальный метод string ToString() для формирования строки со значениями всех полей класса. Новая версия класса ResearchTeam имеет базовый класс Team и следующие поля: • закрытое поле типа string c названием темы исследований; • закрытое поле типа TimeFrame с информацией о продолжительности исследований; • закрытое поле типа System.Collections.ArrayList со списком участников проекта (объектов типа Person); • закрытое поле типа System.Collections.ArrayList для списка публикаций (объектов типа Paper). Код следующих конструкторов, методов и свойств из старой версии класса ResearchTeam необходимо изменить с учетом того, что часть полей класса перемещена в базовый класс Team, и в новой версии класса ResearchTeam для списка публикаций используется тип System.Collections.ArrayList: • конструктор c параметрами типа string, string, int, TimeFrame для инициализации соответствующих полей класса; • конструктор без параметров для инициализации по умолчанию; • свойство типа System.Collections.ArrayList для доступа к полю со списком публикаций; • свойство типа Paper (только с методом get), которое возвращает ссылку на публикацию с самой поздней датой выхода; если список публикаций пустой, свойство возвращает значение null; • метод void AddPapers (params Paper[] ) для добавления элементов в список публикаций; • перегруженная версия виртуального метода string ToString() для формирования строки со значениями всех полей класса, включая список публикаций и список участников проекта; • метод string ToShortString(), который формирует строку со значениями всех полей класса без списка публикаций и списка участников проекта. Дополнительно в новой версии класса ResearchTeam определить • перегруженную версию виртуального метода object DeepCopy(); • свойство типа System.Collections.ArrayList для доступа к полю со списком участников проекта; • метод void AddMembers ( params Person[] ) для добавления элементов в список участников проекта; • свойство типа Team; метод get свойства возвращает объект типа Team, данные которого совпадают с данными подобъекта базового класса, метод set присваивает значения полям из подобъекта базового класса; • реализовать интерфейс INameAndCopy. В новой версии класса ResearchTeam определить • итератор для последовательного перебора участников проекта (объектов типа Person), не имеющих публикаций; • итератор с параметром типа int для перебора публикаций, вышедших за последние n лет, в котором число n передается через параметр итератора. В методе Main()
- Создать два объекта типа Team с совпадающими данными и проверить, что ссылки на объекты не равны, а объекты равны, вывести значения хэш-кодов для объектов.
- В блоке try/catch присвоить свойству с номером регистрации некорректное значение, в обработчике исключения вывести сообщение, переданное через объект-исключение.
- Создать объект типа ResearchTeam, добавить элементы в список публикаций и список участников проекта и вывести данные объекта ResearchTeam.
- Вывести значение свойства Team для объекта типа ResearchTeam.
- С помощью метода DeepCopy() создать полную копию объекта ResearchTeam. Изменить данные в исходном объекте ResearchTeam и вывести копию и исходный объект, полная копия исходного объекта должна остаться без изменений.
- С помощью оператора foreach для итератора, определенного в классе ResearchTeam, вывести список участников проекта, которые не имеют публикаций.
- С помощью оператора foreach для итератора с параметром, определенного в классе ResearchTeam, вывести список всех публикаций, вышедших за последние два года.
Дополнительное задание:
В классе ResearchTeam
• реализовать интерфейс System.Collections.IEnumerable для перебора участников проекта (объектов типа Person), у которых есть публикации; для этого определить вспомогательный класс ResearchTeamEnumerator, реализующий интерфейс System.Collections.IEnumerator.
• определить итератор для перебора участников проекта (объектов типа Person), имеющих более одной публикации, для этого определить метод, содержащий блок итератора и использующий оператор yield.
• определить итератор для перебора публикаций (объектов типа Paper), вышедших за последний год, для этого определить метод, содержащий блок итератора и использующий оператор yield.
В методе Main() - С помощью оператора foreach для объекта типа ResearchTeam вывести список участников проекта, у которых есть публикации.
- С помощью оператора foreach для итератора, определенного в классе ResearchTeam, вывести список участников проекта, имеющих более одной публикации.
- C помощью оператора foreach для итератора, определенного в классе ResearchTeam, вывести список публикаций, вышедших за последний год.