ООП у Delphi

Об'єктно-орієнтоване програмування мовою Object

Мова програмування Object Pascal і його гідний наступник, середовище програмування Delphi, побудовані на основі широкого розвитку на стику 70 - 80-х років 20 століття теорії об'єктно-орієнтованого програмування. У той час ідея опису програм у базисі логічних сутностей та взаємодії між ними не була такою вже безперечною, а в деяких опонентів навіть викликала певне здивування. Переваги ООП у порівнянні з традиційними способами програмування:

1. Ця концепція найбільше відповідає внутрішній логіці функціонування операційної системи Windows. Програма, що складається з окремих об'єктів, добре пристосована до реагування на події, що відбуваються в операційній системі.

2. Велика надійність коду та можливість повторного використання відпрацьованих об'єктів.

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

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

Об'єкт не може виникнути з повітря, середовище програмування якимось чином має бути поінформоване про його характеристики. Тому програміст описує об'єкт; такий опис називається класом. Клас - це креслення майбутнього об'єкта, у якому враховуються як його конструктивні елементи (поля), а й визначаються способи управління цими елементами - методи класу.

type TPeople = class

Клас містить поля (Name, Family) та методи (GetName, GetFamily).

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

var People: TPeople;

People := TPeople.Create; //Виділення пам'яті під об'єкт

Create – це так званий конструктор об'єкта; він завжди присутній у класі та служить для створення та ініціалізації екземплярів. Під час створення об'єкта у пам'яті виділяється місце лише його полів. Методи, як і звичайні процедури та функції, містяться в області коду програми; вони вміють працювати з будь-якими екземплярами свого класу і не дублюються у пам'яті. Після створення об'єкт можна використовувати у програмі: отримувати та встановлювати значення його полів, викликати його методи. Доступ до полів та методів об'єкта відбувається за допомогою уточнених імен, наприклад:

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

Якщо об'єкт стає непотрібним, він повинен бути видалений виклику спеціального методу Destroy, наприклад:

People.Destroy; // Звільнення пам'яті, яку об'єкт займає

Destroy – цетак званий деструктор об'єкта; він є у класі поруч із конструктором і служить видалення об'єкта з динамічної пам'яті. Після виклику деструктора змінна People стає незв'язаною і не повинна використовуватися для доступу до полів і методів об'єкта, що вже не існує. Щоб відрізняти у програмі пов'язані об'єктні змінні від незв'язаних, останнє слід ініціалізувати значенням nil. Приклад:

if People <> nil then People.Destroy;

Виклик деструктора для неіснуючих об'єктів неприпустимий і під час виконання програми призведе до помилки. Щоб позбавити програмістів зайвих помилок, в об'єкти ввели наданий метод Free, який слід викликати замість деструктора. Метод Free сам викликає деструктор Destroy, але тільки в тому випадку, якщо значення об'єктної змінної не дорівнює nil. Тому останній рядок у наведеному вище прикладі можна переписати так:

Після знищення об'єкта змінна People зберігає своє значення, продовжуючи посилатися місце у пам'яті, де об'єкта вже немає. Якщо цю змінну передбачається використовувати, то бажано привласнити їй значення nil, щоб програма могла перевірити, існує об'єкт чи ні. Таким чином, найбільш правильна послідовність дій при знищенні об'єкта має бути такою:

За допомогою стандартної процедури FreeAndNil це можна зробити простіше та елегантніше:

FreeAndNil(People); // Еквівалентно: People. Free; People := nil;

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

var People1, People2: TPeople;

Об'єкти можуть виступати в програмі не тільки як змінні, але такожелементів масивів, полів записів, параметрів процедур та функцій. Крім того, вони можуть бути полями інших об'єктів. У всіх цих випадках програміст фактично оперує вказівниками на екземпляри об'єктів у динамічній пам'яті. Отже, об'єкти спочатку пристосовані до створення складних динамічних структур даних, як-от списки і дерева. Вказівники на об'єкти для цього не потрібні.

People: array of THuman;

Конструктори та деструктори

Особливим різновидом методів є конструктори та деструктори. Створення об'єкта включає виділення пам'яті під екземпляр та ініціалізацію його полів, а руйнування – очищення полів та звільнення пам'яті. Дії з ініціалізації та очищення полів є специфічними для кожного конкретного класу об'єктів. З цієї причини мова Delphi дозволяє перевизначити стандартний конструктор Create та стандартний деструктор Destroy для виконання будь-яких корисних дій. Можна навіть визначити кілька конструкторів та деструкторів (імена їм призначає сам програміст), щоб забезпечити різні процедури створення та руйнування об'єктів.

type TPeople = class Name: string; Family: string; procedure GetName;

процедура GetFamily; construcor Create; destrucot Destroy; end;

//Поки що нічого не робимо

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

то виконується наступнапослідовність дій:

1. У динамічній пам'яті виділяється місце нового об'єкта.

2. Виділена пам'ять заповнюється нулями. В результаті всі числові поля

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

3. Потім виконуються задані програмістом дії конструктора.

4. Посилання на створений об'єкт повертається як значення конструктора. Тип значення, що повертається, збігається з типом класу, використаного при виклику (у нашому прикладі це тип TPeople).

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

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

Деструктор знищує об'єкт, до якого застосовується:

В результаті виконуються:

1. Заданий програмістом код завершення.

2. Звільняється займана об'єктом динамічна пам'ять.

У тілі деструктора зазвичай повинні знищуватися вбудовані об'єкти та динамічні дані, як правило, створені конструктором. Як і звичайні методи деструктор може мати параметри, але ця можливість використовується вкрай рідко.

Writeln('Введіть ім'ялюдини');

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