Перехід у пасивний чи активний стан. 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Перехід у пасивний чи активний стан.



Рух, або переміщення.

Для прийняття елементів стану та поведінки оголошення структури класу об’єктів „точка” матиме вигляд:

TYPE

POINT=object

x,y:integer;

c:byte;

f:boolean;

PROCEDURE SETCOORD (xx,yy:integer);

PROCEDURE SETCOL (cc:byte);

FUNCTION GETXX: integer;

FUNCTION GETYY: integer;

PROCEDURE ON;

PROCEDURE OFF;

PROCEDURE RUH(dx,dy:integer);

END;

PROCEDURE POINT.SETCOORD;

BEGIN

x:=xx;

y:=yy

END;

PROCEDURE POINT.SETCOL;

BEGIN

c:=cc

END;

FUNCTION POINT.GETXX;

BEGIN

GETXX:=x;

END;

FUNCTION POINT.GETYY;

BEGIN

GETYY:=y;

END;

PROCEDURE POINT.ON;

BEGIN

PutPixel(x,y,c);

f:=true;

END;

PROCEDURE POINT.OFF;

BEGIN

PutPixel(x,y,0);

f:=false;

END;

PROCEDURE POINT.RUH;

BEGIN

OFF;

SETCOORD(x+dx,y+dy);

ON;

END;

Після такого оголошення структури і поведінки в програмі можна описати довільну кількість змінних цього об’єктного типу екземплярів класу POINT. Над цими об’єктами можна виконати певні дії:

VAR

a,b:POINT;

BEGIN

ini; {ініціалізація графіки}

a.SETCOORD(100,100);

a.SETCOL(15);

a.ON;

b.SETCOORD(320,200);

b.SETCOL(9);

b.ON;

z:=ReadKey;

a.RUH(50,50);

z:=ReadKey;

b.RUH(-50,-50);

Зауваження. Всі наведенні вище викладки поки що не демонструють жодної переваги ООП, точніше можна сказати, отримали зворотний ефект, програма стала громісткою. Проте всі ці оголошення матимуть ефект, якщо застосувати наступні визначені принципи ООП: наслідування та поліморфізм.

Тема: Ієрархія об’єктів за принципом наслідування.

Як вже відмічалося об’єктно-орієнтовні програми являють собою поведінку в залежності від стану. Об’єкти можуть належати одному класу, це відповідає ієрархії по складу, або ієрархії об’єктів.

Наприклад. Автомобіль складається з двигуна, трансмісії, шасі, електрообладнання, кузова.

Інший варіант ієрархії називається ієрархією по номенклатурі, або ієрархією класів.

Наприклад. Тепловий двигун – різновид механічної машини, двигун внутрішнього згорання – різновид теплового двигуна, карбюраторний двигун – різновид ДВЗ, двигун ВАЗ2106 – різновид карбюраторного двигуна.

Для побудови ієрархії класів використовують другий визначальний принцип – наслідування, при цьому це відношення пов'язує два класи об’єктів, що називаються відповідно предком та нащадком.

Нащадок успадковує всю структуру предка. Він може мати без власного оголошення ті ж поля даних і методів, окремі методи можуть бути перевизначені. Також можуть бути добавленні нові поля даних і методи. Звузити ж структуру не можна. Це означає, що наслідування дає такий же ж за кількістю полів або ширший клас об’єктів.

При оголошенні нового класу нащадка, описуються тільки нові і перевизначені поля даних. Новий клас будується теж при допомозі службового слова object, після якого в дужках вказується ім'я предка.

На основі класу „точка” можна побудувати декілька класів нащадків, що визначають класи як контури, а з них нові класи фігур, як площі, обмежені цим контуром. Є три ієрархії в глибину і на кожному рівні три класи у ширину. Остання ієрархія буде ієрархією по-складу.

Наприклад. В якості прикладу розглянемо клас нащадок „коло на екрані”, що побудоване від предка „точка”.

Поля даних x,y,c,f повністю успадковуються, потрібно добавити елемент стану радіус, також успадковуються методи, потрібно перевизначити методи ON,OFF, крім цього потрібно добавити методи задання та повідомлення радіусу, таким чином оголошення класу має вигляд:

CIRCLE=object(POINT)

r:integer;

PROCEDURE SETR(rr:integer);

FUNCTION GETR: integer;

PROCEDURE ON;

PROCEDURE OFF;

END;

PROCEDURE CIRCLE.SETR;

BEGIN

r:=rr

END;

FUNCTION CIRCLE.GETR;

BEGIN

GETR:=r

END;

PROCEDURE CIRCLE.ON;

BEGIN

SetColor(c);

Graph.Circle(x,y,r);

f:=true

END;

PROCEDURE CIRCLE.OFF;

BEGIN

SetColor(0);

Graph.Circle(x,y,r);

f:=false

END;

 

Аналогічним чином можна побудувати наступного нащадка „круг” на основі класу „коло”, при цьому структура класу буде та ж сама, тільки зміниться реалізація двох методів.

Аналогічно класу point можна побудувати класи „прямокутник” та „рівнобедрений трикутник”

VAR

a1,a2:POINT;

b1,b2:CIRCLE;

.........

BEGIN

.........

With a1 do

Begin

SETCOORD(100,100);

SETCOL(5);

ON

end;

With b1 do

Begin

SETCOORD(200,200);

SETCOL(6);

SETR(20);

ON

end;

a2:=a1;

a2.ON;

b2:=b1;

b2.ON;

a1:=b2;

b1:=a2;

Стосовно даного прикладу можна зробити наступні зауваження:

Подібно до записів в іменах полів даних і методів об’єктів використовують складені ідентифікатори. З метою зменшення кількості узагальнюючого імені об’єкта можна користуватися оператором над записів with do.

Об’єкт-нащадок b1 використовує методи від об’єкта класу точка, а також перевизначений метод ON.

Між об’єктами одного класу можна виконувати операцію присвоєння, при цьому об’єкт, якому присвоюється деяке значення a2, b2 отримує той самий стан, що і об’єкт, від якого здійснюється присвоєння.

При присвоєнні копіюється лише стан, а сама поведінка повинна бути реалізована явним викликом відповідних методів.

Операцію присвоєння можна виконувати не лише між об’єктами одного класу, а також можна виконувати присвоєння між екземплярами різних класів, але якщо вони пов’язані принципом наслідування, причому лише від нащадка до предка і не навпаки. Це означає, що при операції присвоєння, повинні бути передані дані до всіх полів об’єкта, якому присвоюється деяке значення. Надлишок даних від об’єкта, від якого здійснюється присвоєння є несуттєвим.

В розглянутому прикладі вже з'явилися перші прояву ефективності ООП, зокрема побудова ієрархії класів за принципом наслідування. Наслідування дозволило використовувати один раз оголошену структуру батьківського класу у всіх класів нащадка.

Ще один важливий момент ООП пов’язаний із використанням такої властивості об’єктів, як поліморфізм.

Тема: Поліморфізм. Віртуальні методи.

Розглянутий раніше приклад побудови нащадка Circle на перший погляд є довершений і правильним. Особливо ефективним видається метод ruh, який оголошений у структурі класу предка.

Цей метод повністю успадковується нащадками. Реалізація його використовує два методи, що перевизначаються у кожному класі нащадка.

Виконаємо цей метод для двох об’єктів класу point та circle.

VAR

a:POINT;

b:SIRCLE;

BEGIN

......

a.SETCOORD(100, 100);

a.SETCOL (5);

a.ON;

A.RUH (50,50)

END.

Така послідовність команд переведе в активний стан об’єкт „точка” в положення з координатами (100,100) з кольором (5), потім починається виконуватися метод рух, який у свою чергу передбачає виклик методів ON, OFF.

Точка переміститься на 50 пікселів вліво і вниз.

b.SETCOORD(200,200);

b.SETR(20);

b.SETCOL(6);

b.ON;

b.RUH(50,50);

Перші чотири оператори відобразять коло радіусом 20 точок за в точці (200, 200) з кольором 6, потім метод рух перемістить раніше розглянуту точку а в центр кола. Таке явище пов’язане із специфічною ситуацією компіляції та виконання програми, що називається раннім зв’язуванням коду методу із іменем об’єкта.

Звернення до ruh призводить до пошуку в межах коду об’єкта в класі circle. Реалізація методу явно відсутній в структурі класу circle, а успадковується від point, то компілятор здійснює пошук коду цього методу у предка. Знайшовши цей метод компілятор передає управління у код об’єкта класу point.

Виконання методу ruh пов’язаний із трьома діями, хоча методи ON i OFF є перевизначеними у circle, проте виявляється, що виконуються не вони, а методи класу предка. Така послідовність дій виключить точку з координатами (150,150) і включить її в координати (200,200), а коло залишиться нерухомим. В цьому випадку не спрацювали перевизначені методи ON та OFF у класі circle. Це пов’язано з тим, що вони входять в реалізацію методу ruh класу point, а отже „жорстко зв’язані” з іменем цього об’єкта (раннє зв’язування).

Якщо ж по-окремо виконати наступні дії:

b.OFF;

b.SETCOORD(50,50);

b.ON;

То дійсно переміститься коло. В цьому випадку спрацюють власні методи, оскільки вони пов’язані з іменем об’єкта b.

Щоб уникнути подібної ситуації, пов’язаної з раннім зв’язуванням кодів перевизначених методів з іменами даних об’єктів, використовують віртуальні методи. В даному випадку віртуальними методами мають бути ON і OFF.

TYPE

POINT=object

x,y:integer;

c:byte;

f:boolean;

PROCEDURE SETCOORD (xx,yy:integer);

PROCEDURE SETCOL (cc:byte);

FUNCTION GETXX: integer;

FUNCTION GETYY: integer;

PROCEDURE ON; virtual;

PROCEDURE OFF;virtual;

PROCEDURE RUH(dx,dy:integer);

END;

Віртуальні методи вже будуть працювати по-своєму для кожного класу, тобто при виклику методу b.RUH, спочатку відбудеться передача управління у код об’єкта класу point, оскільки перший із методів у реалізації RUH є перевизначеним віртуальним методом OFF, то відбудеться повернення у код об’єкта класу circle (спрацьовує власний OFF).

Код віртуального методу не зв’язується з іменем об’єкта на етапі компіляції. Для віртуальних методів формується так званий пізній зв’язок на етапі виконання програми, в залежності від того, у якому контексті цей метод викликається.

Використання віртуальних методів передбачає декілька стандартних правил:

1. Віртуальним варто оголошувати лише той метод, який:

а). перевизначається у кожному нащадку, тобто в кожному працює по-своєму;

б). входить у склад реалізації іншого методу у предку;

в). містить у реалізації віртуальній, має успадкуватися нащадками без пере визначення.

2. „Один раз віртуальний – все життя віртуальний”. Це означає, що на деякому рівні ієрархії класів певний метод був оголошений віртуально, то на всіх нижчих видів ієрархії, тобто у всіх нащадках цей метод повинен перевизначеним і віртуальним.



Поделиться:


Последнее изменение этой страницы: 2016-09-19; просмотров: 231; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.191.147.190 (0.029 с.)