Реализация концепций «наследования» и «полиморфизма» в объектно-ориентированном программировании на примере создания двух классов. Интерфейсы ICloneable, IEquatable
Содержание
- Условие задачи
- Математическая постановка задачи
- Выполнение
- 1. Создание нового проекта.
- 2. Размещение элементов управления на форме.
- 3. Настройка свойств элементов управления.
- 4. Классы, необходимые для решения задачи.
- 5. Реализация конструкторов класса Point.
- 6. Реализация конструкторов класса Circle.
- 7. Реализация методов класса Point.
- 8. Реализация методов класса Circle.
- 9. Примеры использования конструкторов и методов классов Point и Circle.
- 10. Предварительный исходный код классов.
- 11. Реализация свойств класса Point.
- 12. Реализация свойств класса Circle.
- 13. Реализация методов интерфейса ICloneable в классах.
- 14. Реализация методов интерфейса IEquatable.
- 15. Реализация метода вычисления площади круга в классе Circle.
- 16. Сокращенный листинг класса Point.
- 17. Сокращенный листинг класса Circle.
- 18. Программирование обработчика события клика на кнопке «Вычислить«.
- Связанные темы
Поиск на других ресурсах:
Условие задачи
В разработанных классах необходимо реализовать такие концепции ООП как «наследование» и «полиморфизм«.
Нужно описать базовый класс (класс-предок) и унаследовать (наследовать) от него. Часть функциональности классов нужно реализовать с использованием свойств.
Каждый класс должен содержать реализацию по крайней мере:
- двух конструкторов;
- двух методов;
- двух свойств;
- двух интерфейсов.
Необходимо переопределить операции над объектами классов. Создать класс, который определяет окружность на плоскости. Используя разработанные классы найти площадь круга.
Реализовать интерфейсы ICloneable, IEquatable.
⇑
Математическая постановка задачи
На рисунке 1 изображена окружность на плоскости.
Рис. 1. Изображение окружности на плоскости
Как видно из рисунка 1, для обозначения окружности на плоскости нужно иметь:
- координаты (x, y) точки середины окружности;
- радиус окружности R.
Площадь окружности исчисляется по формуле:
где S — площадь окружности; R — радиус окружности; π– константа, которая равняется 3.1415.
⇑
Выполнение
1. Создание нового проекта.
Запустить Microsoft Visual Studio. Создать новый проект как Windows Forms Application. Пример создания нового проекта приведен здесь.
Автоматически будет создана новая форма приложения.
⇑
2. Размещение элементов управления на форме.
Разместить на форме следующие элементы управления (рисунок 2):
- два элемента управления типа Label. Автоматически будут созданы объекты с именами label1 и label2;
- элемент управления типа TextBox. Создается новый объект с именем textBox1;
- элемент управления типа Button. Создается объект с именем button1.
Рис. 2. Размещение элементов управления на форме
⇑
3. Настройка свойств элементов управления.
Настроить следующие свойства элементов управления (рисунок 3):
- в элементе управления label1 свойство Text = «R = «;
- в элементе управления label2 свойство Text = «S = «;
- в элементе управления button1 свойство Text = «Вычислить«;
- в элементе управления Form1 свойство Text = «Площадь круга«.
Рис. 3. Форма приложения после настройки элементов управления
После настройки формы нужно заняться созданием классов.
⇑
4. Классы, необходимые для решения задачи.
В соответствии с условием задачи, нужно создать два класса:
- класс Point, отображающий точку на плоскости. Этот класс должен быть базовым;
- класс Circle, отображающий круг. Этот класс должен унаследовать данные и методы класса Point (в соответствии с условием задачи).
В данной задаче класс Point называется базовым, а класс Circle – производным.
Итак, возникает иерархия с 2-х классов. Схема иерархии классов и отображение данных (полей) в классах изображенная на рисунке 4.
Рис. 4. Иерархия классов в соответствии с условием задачи
По ходу решения задачи в классы будут вноситься изменения: свойства и методы.
Опишем класс Point, содержащий только данные. На языке C# листинг класса Point будет следующий:
class Point { // поля класса объявлены как protected protected float x; // координата x точки protected float y; // координата y точки }
В классе Point данные класса описываются как protected. Это означает, что эти данные есть видимыми в производных классах и невидимыми извне (скрытые для доступа через объект класса).
Для доступа к данным будут использоваться свойства и специальные методы.
Таким же образом создается класс Circle. Пока что листинг класса Circle следующий:
class Circle:Point // наследует данные из класса Point { // поля класса private float R; // радиус окружности }
В описании класса Circle, начало строки
class Circle:Point
означает, что класс Circle наследует данные и методы класса Point.
Таким образом, на данный момент, в классе Circle есть доступными три поля:
- поле x из унаследованного класса Point;
- поле y из унаследованного класса Point;
- поле R, которое есть внутренним полем класса Circle.
⇑
5. Реализация конструкторов класса Point.
В соответствии с условием задачи, каждый из классов должен содержать минимум два конструктора.
Последовательно в текст класса Point нужно добавить два конструктора. Первый конструктор без параметров инициализирует данные нулевыми значениями.
Второй конструктор – параметризованный. Этот конструктор получает входящими 2 параметра и устанавливает новые значения для внутренних переменных x и y.
Ниже приведен текст программного кода обоих конструкторов:
// конструктор 1 - без параметров public Point() { x = 0f; // обнуление значений координат y = 0f; } // конструктор 2 - с двумя параметрами public Point(float nx, float ny) { x = nx; y = ny; }
Следует обратить внимание, что конструкторы имеют тип доступа public, так как они вызываются извне при создании объекта класса.
⇑
6. Реализация конструкторов класса Circle.
Таким же образом нужно добавить два конструктора в класс Circle.
// конструктор 1 - инициализирует поля нулевыми значениями public Circle() { x = 0f; // 0f - означает, что это значение имеет тип float y = 0f; R = 0f; } // конструктор 2 - с тремя параметрами public Circle(float nx, float ny, float nR) { x = nx; y = ny; R = nR; }
⇑
7. Реализация методов класса Point.
В соответствии с условием задачи, в каждом классе должны быть реализованы два метода. Реализуем методы, которые выполняют следующие действия:
- метод GetPoint(), возвращающий точку типа Point;
- метод SetXY(), устанавливающий новые значения внутренних переменных класса Point.
Тип доступа для методов выбран как public.
Листинг методов следующий.
public Point GetPoint() { Point p; // описывается переменная (объект), для которой память еще не выделена p = new Point(x,y); // выделяется память, создается новый экземпляр класса return p; } // метод, который устанавливает новые значения внутренних переменных public void SetXY(float nx, float ny) { x = nx; y = ny; }
⇑
8. Реализация методов класса Circle.
Подобным образом создаются методы класса Circle. В классе Circle реализуются два метода. Первый метод GetCircle() возвращает объект (с выделением памяти) типа Circle.
Второй метод SetXYR() устанавливает новые значения внутренних переменных. Этот метод получает входными 3 параметра (координаты x, y и радиус R окружности). В методе продемонстрировано использование ключевого слова this для доступа к полям класса. В этом случае имена локальных переменных-параметров совпадают с именами полей класса и скрывают их видимость внутри метода.
Листинг методов следующий:
// методы класса Circle в соответствии с условием задачи // метод, который получает новый экземпляр класса типа Circle public Circle GetCircle() { Circle c; c = new Circle(x, y, R); return c; } // метод, который устанавливает новые значения во внутренние поля класса Circle public void SetXYR(float x, float y, float R) { // пример использования ключевого слова this // во внутреннюю переменную x класса заносится значение локальной переменной x метода SetXYR() this.x = x; // так же заполняются внутренние переменные y и R класса Circle this.y = y; this.R = R; }
⇑
9. Примеры использования конструкторов и методов классов Point и Circle.
Приведем несколько примеров использования конструкторов и методов классов Point и Circle.
Демонстрация методов GetPoint() и SetXY():
// класс Point // вызов конструктора без параметров класса Point() Point p = new Point(); Point p1 = null, p2 = null; p1 = new Point(4.5f, 3.2f); // вызов конструктора с двумя параметрами p2 = p1.GetPoint(); p2.SetXY(3.3f, -2.8f); // установить новые значения // класс Circle Circle c = new Circle(); // конструктор без параметров Circle c1, c2; c1 = new Circle(3.3f, -2.8f, 12f); // выделение памяти c2 = c1.GetCircle(); // метод GetCircle() c2.SetXYR(3.8f, -1.9f, 8f); // метод SetXYR()
⇑
10. Исходный код классов.
На данный момент классы Point и Circle имеют следующий вид:
// описание класса Point class Point { // поля класса объявлены как protected protected float x; // координата x точки protected float y; // координата y точки // конструктор 1 - без параметров public Point() { x = 0f; y = 0f; } // конструктор 2 - с двумя параметрами public Point(float nx, float ny) { x = nx; y = ny; } public Point GetPoint() { Point p; // описывается переменная (объект), для которой память еще не выделена p = new Point(x,y); // выделяется память, создается новый экземпляр класса return p; } // метод, который устанавливает новые значения внутренних переменных public void SetXY(float nx, float ny) { x = nx; y = ny; } } // описание класса Circle class Circle:Point // наследует данные класса Point { // поля класса private float R; // радиус окружности // конструктор 1 - инициализирует поля нулевыми значениями public Circle() { x = 0f; y = 0f; R = 0f; } // конструктор 2 - с тремя параметрами public Circle(float nx, float ny, float nR) { x = nx; y = ny; R = nR; } // методы класса Circle в соответствии с условием задачи // метод, который получает новый экземпляр класса типа Circle public Circle GetCircle() { Circle c; // создается новый объект типа класс Circle c = new Circle(x, y, R); // выделяется память для объекта c, создается экземпляр класса return c; } // метод, который устанавливает новые значения во внутренние поля класса Circle public void SetXYR(float x, float y, float R) { // пример использования ключевого слова this this.x = x; // во внутреннюю переменную x класса заносится значение локальной переменной x метода SetXYR() this.y = y; // так же заполняются внутренние переменные y и R класса Circle this.R = R; } }
⇑
11. Реализация свойств класса Point.
Следующим шагом нужно создать два свойства класса Point.
Первое свойство возвращает или устанавливает значение координат точки x. Второе свойство возвращает/устанавливает значение координаты y.
Имя первого свойства XX. Имя второго свойства YY.
Листинг свойств XX и YY следующий:
// свойство, которое возвращает/устанавливает координату x public float XX { get { return x; } set { x = value; } } // свойство, которое возвращает/устанавливает координату y public float YY { get { return y; } set { y = value; } }
После такого описания свойства XX и YY можно использовать. Далее приведен пример использования свойств XX и YY.
... Point p = new Point(5.2f, 6.35f); // создание объекта типа Point float x,y; x = p.XX; // x = 5.2 y = p.YY; // y = 6.35 // переопределить значения p.XX = 2.33f; p.YY = -3.8f; x = p.XX; // x = 2.33 y = p.YY; // y = -3.8 ...
⇑
12. Реализация свойств класса Circle.
Аналогичным образом описываются свойства класса Circle. Первое свойство читает/устанавливает значение радиуса R. Второе свойство читает/устанавливает значение точки, которая есть центром кола (класс Point).
// свойства класса Circle // свойство, которое возвращает значение радиуса окружности R public float RR { get { return R; } set { R = value; } } // свойство, которое возвращает значение точки типа Point, которая есть центром окружности public Point PP { get { Point p; p = new Point(x, y); return p; } set { x = value.XX; y = value.YY; } }
В нижеследующем листинге описывается пример использования свойств PP и RR.
// создание объекта, в котором значение полей x = 5.5; y = -2.3; R = 12.8 Circle c = new Circle(5.5f, -2.3f, 12.8f); float x, y, R; // доступ к свойству PP класса Circle x = c.PP.XX; // x = 5.5 y = c.PP.YY; // y = -2.3 // доступ к свойству RR R = c.RR; // R = 12.8 c.RR = -20.85f;
⇑
13. Реализация методов интерфейса ICloneable в классах.
Если реализовать интерфейс ICloneable, то можно обеспечить глубокое копирование объектов.
В нижеследующем примере осуществляется поверхностное копирование объектов:
Point p1 = new Point(5.3f, -6.8f); Point p2; // поверхностное копирование p2 = p1; // оба объекта указывают на один участок памяти
Интерфейс ICloneable представляет один метод для реализации. Этот метод называется Clone(). Этот метод нужно реализовать в классах Point и Circle. Реализация метода работает по одинаковому принципу.
Прежде всего нужно изменить заголовок класса Point. Вместо текста
class Point
нужно набрать
class Point:ICloneable
Это означает, что в классе Point нужно реализовать единственный метод Clone(). Листинг метода следующий:
// реализация метода Clone() в интерфейсе ICloneable public object Clone() { Point p = new Point(x, y); return p; }
Так как класс Circle наследует класс Point, который наследует интерфейс ICloneable, то в классе Circle также можно реализовать метод Clone() (но не обязательно).
// Реализация интерфейса ICloneable в классе Circle public object Clone() { Circle c = new Circle(); return c; }
Пример использования метода Clone().
Point p1 = new Point(5.2f, 6.35f); // создание объекта Point p2; // глубокое копирование, так как реализован метод Clone() p2 = (Point)p1.Clone();// для p2 отдельно выделяется память // класс Circle Circle c1 = new Circle(3.2f, -8.3f, 11f); Circle c2 = null; c2 = (Circle)c1.Clone(); // для c2 отдельно выделяется оперативная память
⇑
14. Реализация методов интерфейса IEquatable.
Интерфейс IEquatable реализуется в тех классах, где нужно определить порядок сравнения двух объектов на равенство их значений. В этом интерфейсе определяется только один метод Equals(). Этот метод возвращает значение true, если значение вызывающего объекта есть равным значению другого объекта, который является параметром в методе Equals().
Для класса Point реализуем метод Equals(), который сравнивает на равенство значения переменных x и y.
Листинг метода Equals() для класса Point следующий:
// реализация метода Equals() из интерфейса IEquatable public bool Equals(Point p2) { if ((this.x == p2.x) && (this.y == p2.y)) return true; else return false; }
Листинг метода Equals() для класса Circle следующий:
// Реализация метода Equals() из интерфейса IEquatable public bool Equals(Circle c2) { if ((this.x == c2.x) && (this.y == c2.y) && (this.R == c2.R)) return true; else return false; }
В программе метод Equals() для классов можно использовать следующим образом:
// демонстрация метода Equals() для класса Point Point p1 = new Point(3f, -5.5f); Point p2; bool f; p2 = (Point)p1.Clone(); f = p1.Equals(p2); // f = true // демонстрация метода Equals() для класса Circle Circle c1 = new Circle(3.2f, -8.3f, 11f); Circle c2 = new Circle(3.2f, -8.3f, 11f); f = c1.Equals(c2); // f = true
⇑
15. Реализация метода вычисления площади круга в классе Circle.
Название метода – GetSquare(). Для вычисления площади круга нужно иметь только радиус R. Радиус получается с внутренней переменной R. Результат вычисления есть тип float.
В тексте класса Circle нужно добавить следующий метод:
// Метод, который вычисляет площадь круга public float GetSquare() { const float pi = 3.1415f; float s; s = pi * R * R; return s; }
⇑
16. Сокращенный листинг класса Point.
Итак, создание классов завершено.
Сокращенный листинг класса Point следующий (детали реализации описываются в предыдущих пунктах):
class Point:ICloneable,IEquatable<Point> { // поля класса объявленные как protected protected float x; // координата x точки protected float y; // координата y точки // конструктор 1 - без параметров public Point() { ... } // конструктор 2 - с двумя параметрами public Point(float nx, float ny) { ... } // метод, который возвращает точку с координатами public Point GetPoint() { ... } // метод, который устанавливает новые значения внутренних переменных public void SetXY(float nx, float ny) { ... } // свойство, которое возвращает/устанавливает координату x public float XX { get { ... } set { ... } } // свойство, которое возвращает/устанавливает координату y public float YY { get { ... } set { ... } } // реализация метода Clone() в интерфейсе ICloneable public object Clone() { ... } // реализация метода Equals() из интерфейса IEquatable public bool Equals(Point p2) { ... } }
⇑
17. Сокращенный листинг класса Circle.
Низшее приведен листинг класса Circle, в котором скрыты детали реализации. Реализация методов, свойств, конструкторов описывается в предыдущих пунктах.
class Circle:Point // наследует данные класса Point { // поля класса private float R; // радиус окружности // конструктор 1 - инициализирует поля нулевыми значениями public Circle() { ... } // конструктор 2 - с тремя параметрами public Circle(float nx, float ny, float nR) { ... } // методы класса Circle в соответствии с условием задачи // метод, который получает новый экземпляр класса типа Circle public Circle GetCircle() { ... } // метод, который устанавливает новые значения во внутренние поля класса Circle public void SetXYR(float x, float y, float R) { ... } // свойства класса Circle // свойство, которое возвращает значение радиуса окружности R public float RR { get { ... } set { ... } } // свойство, которое возвращает значение точки типа Point, которая есть центром окружности public Point PP { get { ... } set { ... } } // Реализация интерфейса ICloneable public object Clone() { ... } // Реализация метода Equals() из интерфейса IEquatable public bool Equals(Circle c2) { ... } // Метод, который вычисляет площадь круга public float GetSquare() { ... } }
⇑
18. Программирование обработчика события клика на кнопке «Вычислить«.
Вычисление площади круга осуществляется в момент, когда пользователь сделает клик на кнопке «Вычислить«. Листинг обработчика события клика на кнопке «Вычислить» следующий:
private void button1_Click(object sender, EventArgs e) { Circle c = new Circle(); float s; // заполнить значения R c.RR = (float)Double.Parse(textBox1.Text); // вызвать метод определения площади круга s = c.GetSquare(); label2.Text = "S = " + s.ToString(); }
Результат работы программы изображен на рисунке 5.
Рис. 5. Выполнение программы
⇑
Связанные темы
⇑