Лабораторная работа 2 «Наследование».
В классе: Реализуем два класса: «Точка на плоскости» (Point) и «Круг на плоскости» (Circle). Реализацию каждого класса оформим в отдельном модуле.
1. Объекты класса «Точка на плоскости» (Point) будут характеризоваться двумя полями «x» и «y», хранящими координаты точки на плоскости и методами: конструктор Point() – создание точки в начале координат; конструктор Point(x,y) – создание точки с указанными координатами; процедура Move(dx,dy) – перенос точки на вектор (dx,dy); функция Info – возвращает строку с информацией об объекте.
2. Объекты класса «Круг на плоскости» (Circle) будут характеризоваться тремя полями «x», «y» и «r», хранящими соответственно координаты центра круга и его радиус. Также объект должен обладать следующими методами: конструктор Circle() – создание круга с параметрами (0,0,1); конструктор Circle(x,y,r) – создание круга с указанными параметрами; процедура Move(dx,dy) – перенос круга на вектор (dx,dy); функция GetSquare() – возвращает значение площади круга; процедура SetSquare(Value) – изменяет площадь круга на значение (Value); функция Info() – возвращает строку с информацией об объекте.
Логично данный класс не описывать «с нуля», а построить его на базе класса (Point). В этом случае, очевидно, что процедура Move(dx,dy) в классах (Circle) и (Point) выполняет аналогичные действия и может быть унаследована. Функция Info() также есть в обоих классах, но в (TCircle) выводится больше информации, поэтому создадим новый метод, перекрыв старый. Остальные методы уникальны. Их также опишем в классе – потомке.
Диаграмма классов
Для доступа к полям x и y класса Point из его потомков и закрытия данных полей от остальных классов, эти поля объявляются с уровнем доступа protected (#).
Текст файла «Points.cs»:
Возможна следующая реализация класса Circle:
Как видно, конструктор класса «Круг»
повторяет действия конструктора базового класса «Точка»
В этом случае конструктор класса «Круг» можно записать короче
указывая в его заголовке, что он сначала исполняет действия конструктора базового класса с указанными параметрами.
3. Тестирование классов выполним в консольном приложении, в несколько этапов.
На первом этапе просто проверим для каждого класса работу конструкторов и методов Info().
Здесь создаются два объекта класса «Точка» и два объекта класса «Круг». Первые из этих объектов создаются конструкторами без параметров, а вторые – конструкторами с параметрами. Информация о каждом объекте выводится на консоль:
Очевидно, что конструкторы работают корректно.
На втором этапе будем использовать принцип полиморфизма. Для этого опишем массив объектов, указав тип каждого элемента как «Точка». Создание объектов оформим в методе Create(), а вывод информации – в методе Show().
static void Main(string[] args) { const int n = 6; //длина массива Point[] p; Create(out p, n); Show(p); Console.ReadLine(); }
В методе Create() будем создавать объекты и класса «Точка» и класса «Круг».
static void Create(out Point[] p, int k) { p = new Point[k]; Random rnd = new Random(); for (int i = 0; i < k; i++) { if (rnd.NextDouble() < 0.4) else p[i] = new Circle(rnd.Next(10), rnd.Next(10), rnd.Next(8)); } }
Класс объекта p[i] выбирается случайно. С вероятностью 0.4 это будет точка, а с вероятностью 0.6 – круг. Вывод информации об объектах оформим в виде:
static void Show(Point[] p) { int k = p.Length; for (int i = 0; i < k; i++) { Console.WriteLine("{0,2} - {1}",i,p[i].Info()); } Console.WriteLine("-------------------------------"); }
В итоге, результат работы программы следующий:
Т.к. в методе Show() элементы массива p объявлены как объекты базового класса «Точка», то компилятор подставляет в качестве адреса функции Info() адрес данной функции из класса «Точка» (т.н. «раннее связывание»). Если фактический класс отличается от базового, то следует сначала проверить это, а затем привести объект к правильному типу (кастинг). Заменим текст метода Show(). static void Show2(Point[] p) { int k = p.Length; for (int i = 0; i < k; i++) { if (p[i] is Point) Console.WriteLine("{0,2} - {1}", i, p[i].Info()); else Console.WriteLine("{0,2} - {1}", i, ((Circle)p[i]).Info()); } Console.WriteLine("-------------------------------"); } Здесь для объектов класса «Точка» вызывается базовый Info(), а для остальных типов – метод Info() класса «Круг». Однако результат остаётся прежним:
Наша ошибка в том, что все эти объекты являются объектами базового класса и условие в операторе if (p[i] is Point) всегда даёт значение true. Поменяем данное условие на более точное условие (p[i] is Circle)
static void Show3(Point[] p) { int k = p.Length; for (int i = 0; i < k; i++) { if (p[i] is Circle) Console.WriteLine("{0,2} - {1}", i, ((Circle)p[i]).Info()); else Console.WriteLine("{0,2} - {1}", i, p[i].Info()); } Console.WriteLine("-------------------------------"); }
Теперь проверка работает корректно.
На третьем этапе добавим тестирование остальных методов класса. Для этого в теле программы организуем метод Transform(), включающий вызов методов наших классов. static void Transform(Point[] p) { for (int i = 0; i < p.Length; i++) { if (p[i] is Circle) ((Circle)p[i]).SetSquare(10); else p[i].Move(5,5); } }
Будем вызывать его, а затем метод Show() для проверки результатов:
static void Main(string[] args) { const int n = 6; //длина массива Point[] p; Create(out p, n); Show(p); Transform(p); Show(p);
Console.ReadLine(); }
Результат запуска программы следующий.
Самостоятельно в классе
Реализовать в обоих классах следующие методы: Simm() – переносит объект симметрично относительно начала координат. Для проверки работы метода примените его ко всем объектам и выполните (Show). RoFrom(А) – расстояние до другого объекта (А). Здесь следует учесть, что для класса (Point) объект A должен быть этого же типа (т.к. Circle ещё не описан), а для класса (Circle) объект A может иметь и тот и другой тип (быть и точкой и кругом). Для проверки второго метода выведите квадратную таблицу N на N с подписями строк и столбцов, содержащую расстояние от i-го объекта до j-го (для желающих получить 4 или 5 на экзамене).
Дома:
Обязательная часть:
Воспользуйтесь поиском по сайту: ©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...
|