загрузка...
загрузка...
На головну

Класи, екземпляри класу, успадкування, ієрархія.

  1.  Ієрархія.
  2.  Лекція 9. ГЕНЕТИКА підлоги і зчеплене зі статтю успадкування
  3.  Спадкування, залежне від статі
  4.  Суб'єкти політичної влади: класи, соціально-політичні спільності, еліти і групи. Механізм здійснення політичної влади
  5.  Цитоплазматичне спадкування, його особливості

Об'єктний тип (наприклад, tDot) називається класом. Мінлива даного типу - об'єкт або, що те ж саме, екземпляр класу. Тобто при завданні

Var dDot: tDot

змінна dDot - це об'єкт.

tDot - тип-прабатько (клас-прабатько),

· TCircle =

object (tDot) {тип-спадкоємець (клас-спадкоємець)};

...

end;

· TRectangle =

object (tDot) {інший спадкоємець};

...

end;

Тут tCircle і tRectangle - прямі нащадки tDot (тобто він їх прямий прабатько) і т.п.

Далі можна визначити інші класи-спадкоємці:

· TTriangle =

object (tDot)

...

end;

· TFilledTriangle =

object (tTriangle)

...

end;

· TFilledCircle =

object (tCircle)

...

end;

· TRedCirlce =

object (tCirlce)

...

end;

· TGreenCirlce =

object (tCirlce)

...

end;

· TFilledRectangle =

object (tRectangle)

...

end;

Ієрархія цих класів:

       
   
 
 


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

приклад:

type

tDot =

object

active: Boolean;

X, Y: Integer;

procedure Show;

procedure Hide;

procedure MoveBy (dX, dY: Integer);

procedure MoveTo (NewX, NewY: Integer);

procedure Init (X_, Y_: Integer);

end;

tCircle =

object (tDot)

radius: Real;

procedure Show;

procedure Hide;

procedure MoveBy (dX, dY: Integer);

procedure MoveTo (NewX, NewY: Integer);

procedure Init (X_, Y_, R_: Integer);

end;

var aDot: tDot;

aCircle: tCircle;

У тілі об'єкта aCircle можна користуватися полями X, Y, active, як якщо б вони були визначені в tCircle, а не в tDot. При цьому вони ніякого відношення не мають до об'єкта aDot, тобто до tDot.X, aDot.Y, aDot.Active. Це aCircle.X, aCircle.Y, aCircle.Active. Але за своєю структурою вони дублюють відповідні поля об'єкта aDot.

А ось виклик методів aCircle.Show, aCircle.Hide і aCircle.Move (...) йде по-іншому. Реально це tCircle.Show, tCircle.Hide і tCircle.Move (...), а методи для aDot - це tDot.Show, tDot.Hide і tDot.Move (...), "налаштовані" на конкретний екземпляр класу, тобто "знаючі", кого показувати, приховувати, переміщати.

Процедура Init перевизначена так, що тепер треба задавати радіус, на відміну від прабатька:

Процедура Init в tCircle перевизначена так, що тепер треба задавати радіус, на відміну від прабатька. Кажуть, що вона перекриває відповідний метод прабатька.

procedure tCircle.Init (X_, Y_, R_: Integer);

begin

tDot.Init (X_, Y_);

R: = R_;

end;

procedure tCircle.Hide;

var TmpColor: Word;

begin

... {Намалювати коло кольором фону}

active: = false;

end;

procedure tCircle.MoveBy (dX, dY: Integer);

begin

Hide;

X: = X + dX;

Y: = Y + dY;

Show;

end;

procedure tCircle.MoveTo (NewX, NewY: Integer);

begin

Hide;

X: = NewX;

Y: = NewY;

Show;

end;

зауваження: В принципі типи полів даних в нащадках перевизначати не можна (в порівнянні з прабатьками). Всі поля, наявні у прабатьків, є і у всіх їх нащадків, плюс нові поля, які додатково визначені для нащадків. Але починаючи з Delphiі в Object PASCAL була введена можливість перекриття полів даних.

Ми поки розглядаємо тільки так звані статичні методи. Вони викликаються так, як скомпільовані для відповідного типу; їх можна перевизначати в нащадках. Але зате кожен раз треба дублювати текст: процедура Move для tCircle абсолютно аналогічна процедурі Move для tDot. Якби ми не описали процедуру tCircle.Move, завдяки спадкоємства зголосилася б tDot.Move! І здалося б переміщення точки, а не кола. Існують також віртуальні методи, які дозволяють забезпечити більшу гнучкість, ніж статичні. Але про них мова піде пізніше.

Часто використовують типи, звані абстрактними, у яких єдине призначення - "ростити" від них спадкоємців "в різні боки", щоб мати в спадкоємців відповідні поля і методи. При цьому зміна реалізації такого класу автоматично "безкоштовно" змінює поведінку всіх нащадків. А ось інтерфейс абстрактних класів намагаються не міняти, інакше треба переписувати майже всю програму - міняти всі виклики відповідних методів в нащадках. У абстрактних класів не буває примірників об'єктів (тобто змінних такого типу - реально викликаються об'єктів).

приклад:

type

tLocation =

object

X, Y: Integer;

procedure Init (X_, Y_: Integer);

function GetX: Integer;

function GetY: Integer;

end;

tDot =

object (tLocation)

active: Boolean;

procedure Init (X_, Y_: Integer);

procedure Show;

procedure Hide;

procedure MoveBy (dX, dY: Integer);

end;

тут tLocation - абстрактний тип; у нього не буде примірників. Зате з будь-якого нащадка можна буде викликати методи GetX і GetY.

Приклад об'єктно-орієнтованої програми: рух фігур по екрану.

unit Figures;

interface

uses ...;

type

tLocation =

object

X, Y: Integer;

procedure Init (X_, Y_: Integer);

function GetX: Integer;

function GetY: Integer;

end;

tpDot = ^ tDot; {Тип 'покажчик на екземпляр класу tDot'. см.далее}

tDot =

object (tLocation)

Aсtive: Boolean;

constructor Init (X_, Y_: Integer); {Конструктор. Див. Далі}

destructor Done; virtual; {Деструктор. Див. Далі}

procedure Show; virtual; {Віртуальний метод. Див. Далі}

procedure Hide; virtual;

function IsActive: Boolean;

procedure MoveBy (dX, dY: Integer); virtual;

procedure MoveTo (newX, newY: Integer); virtual;

end;

tpCircle = ^ tCircle; {Покажчик на екземпляр tCircle}

tCircle =

object (tDot)

R: Integer;

constructor Init (X_, Y_: Integer; R_: Integer);

procedure Show; virtual;

procedure Hide; virtual;

procedure ChangeRadius (dR: Integer); virtual;

end;

{--- Секція реалізації ---}

implementation

{Методи tLocation}

procedure tLocation.Init (X_, Y_: Integer);

begin

X: = X_;

Y: = Y_;

end;

function tLocation.GetX: Integer;

begin

GetX: = X;

end;

function tLocation.GetY: Integer;

begin

GetY: = Y;

end;

{Методи tDot}

constructor tDot.Init (X_, Y_: Integer);

begin

tLocation.Init (X_, Y_);

active: = false;

end;

destructor tDot.Done;

begin

Hide; {це tDot.Hide для об'єкта класу tDot}

end;

procedure tDot.Show;

begin

... {Намалювали поточним кольором}

active: = true; {Позначили стан як активне}

end;

procedure tDot.Hide;

begin

... {Намалювали кольором фону}

active: = false; {Позначили стан як неактивний}

end;

function tDot.IsActive: Boolean;

begin

Result: = active;

end;

procedure tDot.MoveBy (dX, dY: Integer);

begin

Hide; {це tDot.Hideдля об'єкта dDot, tCircle.Hideдля aCircle і т.д.}

X: = X + dX;

Y: = Y + dY;

Show; {TDot.Show для aDot, tCircle.Show для aCirle і т.д.

end;

procedure tDot.MoveTo (newX, newY: Integer);

begin

Hide;

X: = newX;

Y: = newY;

Show;

end;

{Методи tCircle}

constructor tCircle.Init (X_, Y_, R_: Integer);

begin

tDot.Init (X_, Y_); {Ініціалізація прародителя}

R: = R_;

end;

procedure tCircle.Show;

begin

... {Малювання кола}

Active: = true;

end;

procedure tCircle.Hide;

var TmpColor: tColor;

begin

TmpColor: =; {Запам'ятали поточний колір малювання}

... {Встановили поточним колір фону}

... {Намалювали окружність кольором фону, тобто приховали}

... {Відновили поточний колір малювання}

Active: = false; {Позначили стан як неактивний}

end;

procedure tCircle.ChangeRadius (dR: Integer);

begin

Hide;

R: = R + dR;

if R <0 then R: = 0; {Радіус не може бути негативним}

Show;

end;

end.

Як приклад використання модуля Figures напишемо програму, в якій використовуються класи модуля Figures, а також додається спадкоємець класу tCircle. При цьому для нього статичний метод Init і віртуальні методи Show і Hide переписуються заново (як кажуть - перекриваються), а всі інші методи (наприклад, moveBy) успадковуються.

Unit Figure1; {Додавання спадкоємця}

Uses ..., Figures; {Використовуємо модуль Figures}

type

tArc =

object (tCircle)

angle1, angle2: Integer;

construсtor Init (X_, Y_, R_, angle1_, angle2_: Integer);

procedure Show; virtual; {Метод перекривається}

procedure Hide; virtual; {Також перекривається}

end;

var

aArc: tArc;

aCircle: tCircle;

pArc: ^ tArc;

{Методи Arc}

constructor tАrc.Init (X_, Y_, R_, angle1_, angle2_: Integer);

begin

tCircle.Init (X_, Y_, R_);

angle1: = angle1_;

angle2: = angle2_;

end;

procedure tArc.Show;

begin

... {Малюємо дугу поточним кольором}

Active: = true;

end;

procedure tArc.Hide;

var TmpColor: tColor;

begin

TmpColor: = ...; {Запам'ятовуємо поточний колір}

... {Встановлюємо колір фону поточним кольором малювання}

... {Малюємо дугу кольором фону}

Active: = false; {Помічаємо стан як неактивний}

... {Відновлюємо поточний колір}

end;

Form1.Button1Click (...); {після натискання кнопки йде отрисовка фігур}

begin

aCircle.Init (100,100,50); {Ініціалізували поля окружності}

aCircle.MoveTo (10); {щоб зупинити переміщення кола і почати

рухати дугу натисніть }

aArc.Init (120,190,25,0,90); {Ініціалізували поля дуги}

aArc.MoveBy (5,14); * * * * *

end.

 




 Основний принцип структурного програмування |  Основні завдання структурного програмування |  Читання і запис натуральних спеціальні символи, використовувані на ПК. |  Стандартні типи даних. Двійкове подання чисел і додатковий код. |  Найпростіші оператори мови Object PASCAL |  Структурні типи даних |  Покажчики. Динамічні змінні. Динамічне виділення і вивільнення пам'яті |  Процедури і функції. Формальні і фактичні параметри. Передача параметрів за посиланням, за значенням і через покажчик. |  Локальні і глобальні змінні. Побічний ефект функції. Вкладеність процедур і функцій. Правила видимості. |  Приклад на правила видимості і передачі параметрів |

загрузка...
© um.co.ua - учбові матеріали та реферати