C# – Контрольна робота. Реалізація концепцій “спадковості” та “поліморфізму” в об’єктно-орієнтованому програмуванні на прикладі побудови двох класів. Інтерфейси 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 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().
У нашому випадку, реалізуємо метод 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); // ff = 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. Виконання програми
⇑
Зв’язані теми
⇑