Інкапсуляція являє собою об’єднання даних та їх методів всередині класу. Це означає, що в класі інкапсулюються (об’єднуються і поміщаються всередину) поля, властивості і методи. При цьому клас отримує певну функціональність. Наслідування



Скачати 107.63 Kb.
Дата конвертації16.04.2017
Розмір107.63 Kb.




Лекція 3. Особливості об’єктно-орієнтованого програмування на Delphi

Основою об’єктно-орієнтованого програмування (ООП) є ідея об'єднання в одній структурі даних і дій, які виконуються над цими даними.

Починаючи з 7-ї версії в середовищі Delphi для розробки програм використовується мова програмування Delphi, основу якої складає мова Object Pascal (об’єктно-орієнтоване розширення стандартної мови програмування Pascal). Програмування на мові Delphi означає роботу в інтегрованому середовищі розробки програм (IDE) фірми Borland. При цьому система накладає ряд обмежень, які виходять за рамки специфікації мови Object Pascal. Зокрема, посилюються вимоги до іменування файлів та програм, які не є обов’язковими за рамками IDE.

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

До основних концепцій ООП належать наступні.

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

Наслідування – це процес створення нових об’єктів-нащадків від існуючих об’єктів, при чому нащадок наслідує від батьківського об’єкта усі його поля, властивості та методи. Далі наслідувані поля, властивості і методи можна використовувати в незмінному вигляді або перевизначати (модифікувати).

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

Наступна концепція ООП – це поліморфізм. Суть поліморфізму полягає у тому, що методи різних класів можуть мати однакові імена, але різний зміст. Це досягається перевизначенням батьківського методу в класі нащадку. В результаті батьківський метод і нащадок ведуть себе по-різному. При цьому звернення до одноіменних методів різних об’єктів виконується аналогічно.

Класи і об’єкти

В мові програмування Object Pascal класи – це спеціальні типи даних, які використовують для опису об’єктів. Відповідно об’єкт, який має тип якого-небудь класу є екземпляром даного класу або змінною цього типу.

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

Опис класу має наступну структуру:

type <ім’я класу>=class(<ім’я ,батьківського класу>)

private <приватні описи>;

protected <захищені описи>;

public <загальнодоступні описи>;

published <опубліковані описи>;

end;

У приведеній структурі описами є об’явлення властивостей, методів та подій.



Приклад, опису класу:

type TColorCircle=class(TCircle);

FLeft, FTop, FRight, FBottom: Integer;

FColor: TColor;

end;

Тут клас TColorCircle створюється на основі батьківського класу TCircle. В порівнянні з батьківським, новий клас додатково містить чотири поля типу Integer і одне поле типу TColor.



Для різних елементів класу можна встановлювати різні права доступу. Для цього в описі класу використовуються окремі розділи, позначені спеціальними специфікаторами видимості.

Розділи private та protected містять захищені описи, що доступні всередині модуля, в якому вони знаходяться. Описи з розділу protected, крім того, є доступними для породжених класів за межами названого модуля.

Розділ public містить загальнодоступні описи, які видно у будь-якому місці програми, де є доступним даний клас.

Розділ published містить опубліковані описи, які на додаток до загальнодоступних описів породжують динамічну (тобто під час виконання програми) інформацію про тип (Run-Time Type Information, RTTI). За цією інформацією при виконанні програми відбувається перевірка на приналежність елементів об’єкта тому чи іншому класу. Одним з призначень розділу published є забезпечення доступу до властивостей об’єкта при розробці програми. В Інспекторі об’єктів видно ті властивості, які є опублікованими. Специфікатор published встановлюється по замовчуванню.

Об’єкти як екземпляри класу об’являються у програмі в розділі var як звичайні змінні. А для звертання до конкретного елемента об’єкта (до поля, властивості чи методу), як і у випадку запису, вказується ім’я об’єкта та ім’я елемента, розділені крапкою, тобто ім’я елемента є складеним. Наприклад,

var CCircle1: TColorCircle;

begin CCircle1.FLeft:=5;

CCircle1.FTop:=1

end;

Поля класу

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

type TNewClass = class (TObject)

private FCode: integer; FSign: char; FNote: string;

end;

Тут новий клас TNewClass створюється на основі базового класу TObject і має додатково три поля. Відповідно до прийнятої домовленості імена полів повинні починатись з префікса F (від англ. Field – поле).



Якщо в якості первинного класу використовується клас TObject, який є базовим для усіх класів, то його ім’я після слова class можна не вказувати.

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



Властивості об’єкта

Властивості реалізують механізм доступу до полів. Кожній властивості відповідає поле, яке містить значення властивості, і два методи, які забезпечують доступ до даного поля. Опис властивостей починається зі слова property, при цьому тип властивості і відповідного поля повинні співпадати. Ключові слова read і write є зарезервованими всередині об’явлення властивості і служать для вказання методів класу, за допомогою яких виконується зчитування значення поля, пов’язаного з властивістю, або запис нового значення в це поле. Приклад опису властивостей:

type TNewClass=class(TObject)

private


FCode: integer; FSign: char; FNote: string;

published

property Code: integer read FCode write FCode;

property Sign: char read FSign write FSign;

property Note: string read FNote write FNote;

end;


Для доступу до полів FCode, FSign та FNote, які описані в розділі захисту і є недоступними для інших класів, використовуються властивості Code, Sign та Note відповідно.

У контексті програми з властивістю можна працювати як зі звичайним полем.



Методи класу

Метод являє собою підпрограму (процедуру чи функцію), яка є елементом класу. Опис методу подібний до опису звичайної підпрограми модуля. Заголовок методу розміщується в описі класу, а сам код методу знаходиться у розділі реалізації. Ім’я методу у розділі реалізації є складеним і включає в себе тип класу.

Наприклад, опис методу ButClick буде виглядати так:

interface

type TForm1=class(TForm)



But1:TButton;

procedure ButClick(Sender:TObject);

end;



implementation



procedure TForm1.ButClick(Sender:TObject);

begin Close;

end;


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

Але метод, який об’явлений у класі, може викликатись й іншими способами, що залежать від виду цього методу. Вид методу визначається модифікатором, який вказується в описі класу після заголовку методу і відділяється від заголовка крапкою з комою. Наведемо деякі модифікатори: virtual – віртуальний метод; dynamic – динамічний метод; override – перевизначений метод; message – обробка повідомлення; abstract – абстрактний метод.

У розробника існує засіб самому керувати перевизначенням методів на етапі прогонки програми – т.зв. динамічне заміщення методів. Для цього метод, який перевизначається в батьківському класі, визначається модифікатором virtual або dynamic. У класі-нащадку метод, який буде заміщати батьківський, визначається модифікатором override.

Отримавши директиву virtual, компілятор поміщає інформацію про метод в таблицю віртуальних методів класу (Virtual Method Table – VMT). Неважливо, скільки створено об’єктів класу, - для кожного класу створюється лише одна таблиця віртуальних методів, з якою потім береться адреса відповідного віртуального методу. У таблицю віртуальних методів поміщаються адреси усіх віртуальних методів, які унаслідуються від батьківських. Це прискорює пошук потрібного методу, але збільшує розмір таблиці.

Зауважимо, що у всіх віртуальних і відповідних їм віртуально перевизначаючих методів повинні співпадати не лише імена, але і списки формальних параметрів.

Отримавши директиву dynamic, компілятор поміщає інформацію про метод в таблицю динамічних методів класу (Dynamic Method Table – DMT), де міститься його адреса.

Модифікатор override повідомляє компілятору, що даний метод перевизначає відповідний йому віртуальний (або динамічний) метод.

Часто вихідний метод може не виконувати ніяких дій. У цьому випадку метод називається абстрактним, і бажано, щоб в нащадках він перекривався. Для того, щоб об’явити метод абстрактним, після його заголовка і модифікатора virtual або dynamic необхідно поставити модифікатор abstract.

Після об’явлення класу можна створювати об’єкти. Об’єкти можна створювати лише динамічно. Методи, які призначені для створення або видалення об’єктів, називаються конструкторами і деструкторами, відповідно. Опис даних методів відрізняються від опису звичайних процедур лише тим, що у їх заголовках стоять ключові слова constructor та destructor. У якості імен конструкторів та деструкторів у базовому класі TObject і багатьох інших класах використовуються імена Create та Destroy.

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

ObjA:=TOwnClass.Create;

Конструктор виділяє пам’ять для нового об’єкта в ”кучі” (heap), задає нульові значення для порядкових полів, значення nil – для вказівників та полів-класів, стрічкові поля встановлює порожніми, а також повертає вказівник на створений об’єкт.

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

Наведемо приклади використання конструктора і деструктора:

type TShape=class(TGraphicControl)

private


FPen: TPen;

procedure PenChang(Sender:TObject);

public

constructor Create(Owner:TComponent); override;



destructor Destroy; override;

end;


// Опис конструктора Create класу Tshape

constructor Tshape.Create(Owner:TComponent);

begin inherited Create(Owner); // Ініц. успадкованих частин

w:=65; h:=65; //Зміна успадкованих частин

FPen:=TPen.Create; //Ініц. нових полів

FPen.OnChange:=PenChang;

end;

Тут в конструкторі класу-нащадка спочатку викликається конструктор первинного класу, а потім виконуються інші дії. В класі-нащадку директива override (перевизначити) забезпечує можливість первинному класу використовувати новий метод. Ключове слово inherited служить для виклику методів первинного класу.



Повідомлення та події

Для обробки повідомлень, які посилаються ядром Windows і різними програмами, використовуються спеціальні методи, які описуються за допомогою модифікатора , після якого вказується ідентифікатор повідомлення.

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

Як правило в Delphi немає необхідності обов’язкової обробки безпосередніх повідомлень Windows, оскільки у розпорядженні є ще й події, працювати з якими набагато простіше і зручніше. Подія являє собою властивість процедурного типу, яка призначена для забезпечення реакції на ті чи інші дії. Присвоювання значень цій властивості (події) означає вказання методу, який викликається, коли подія відбулась. Відповідні методи називаються обробниками подій. Приклад призначення обробника події:

Application.OnIdle:=IdleWork;

У якості обробника події OnIdle, яка виникає при простої програми, об’єкту програми призначається процедура IdleWork. Оскільки об’єкт Application є доступним лише при виконанні програми, таке присвоювання не можна виконати через Інспектор об’єктів.

Події Delphi мають різні типи, які залежать від виду цієї події. Найпростішим є тип TNotifyEvent, характерний для повідомляючих подій. Цей тип описано так:

type TNotifyEvent= procedure(Sender:TObject) of object;

і містить один параметр Sender, який вказує на об’єкт-джерело події. Багато подій більш складного типу, поряд з іншими параметрами, також мають параметр Sender.

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



Динамічна інформація про тип

Об’єкти містять динамічну інформацію про свій тип (RTTI – Run-Time Type Information) і наслідування, яка є доступною під час виконання програми і яку можна використовувати, наприклад, для перевірки приналежності об’єкта до того чи іншого типу. Оскільки для кожного об’єкта є допустимим лише певні операції, які залежать від його типу, така перевірка дозволяє упередити небезпечні ситуації, пов’язані з виконанням недопустимих дій.

Більшості методів при виклику передається параметр Sender, який має тип TObject. Для виконання з цим параметром таких операцій як, наприклад, виклик методу або присвоювання значення властивості, його необхідно привести до типу того об’єкта, для якого виконуються дані операції. Розрізняють явне і неявне приведення (перетворення) типів.

Для операції з типами в мові Object Pascal служать інструкції is та as.Інструкція використовується у виразі: <Об’єкт> is <Клас> і перевіряє, чи належить об’єкт вказаному класу чи одному з його нащадків. Якщо так, то цей вираз має значення true, що вказує на сумісність типів. В іншому випадку вираз має значення false.

Інструкція as призначена для перетворення одного типу в інший і використовується у виразі: <Об’єкт> as <Клас>. В даному виразі об’єкт приводиться до типу класу, таке перетворення типу є неявним.

Розглянемо приклад неявного перетворення типу:

procedure TForm1.ButClick(Sender:TObject);

begin


if (Sender is TButton)

then (Sender as TButton).Caption:=TimeToSTR(Now);

end;

Тут при натисненні кнопки But1 в її заголовку відображається поточний час. Для доступу до об’єкта кнопки і його властивості Caption використовується параметр Sender, тип якого приводиться до типу TButton. Попередньо виконується перевірка, чи можна виконати подібне перетворення типу.



Якщо обробник призначений лише для кнопки But1, то зміна заголовка кнопки простіше виконати за допомогою інструкції:

But1.Caption:=TimeToSTR(Now);

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

Явне перетворення типу виконується за допомогою інструкції: <Тип>(<Об’єкт>). Приклад явного перетворення типу:

procedure TForm1.ButClick(Sender:TObject);



begin

TButton(Sender).Caption:=’Кнопка’;



end;

Тут заголовок компоненти, натиснутої користувачем, міняється заголовком Кнопка. Для виконання присвоювання тип компоненти приводиться до типу TButton.


База даних захищена авторським правом ©lecture.in.ua 2016
звернутися до адміністрації

    Головна сторінка