- •Курс лекцій
- •Київ-Черкаси 20010
- •1 Об‘єктно-орієнтоване програмування
- •1.1. Складові класу
- •1. Поля
- •2. Методи
- •3. Властивості
- •1.2 Оголошення класу
- •2.1 Стандартні компоненти
- •2 Огляд палітри компонентів
- •2.2 Сторінки Additional та System
- •3 Обробка виняткових ситуацій у delphi
- •Структурна обробка виняткових ситуацій
- •Модель виняткових ситуацій у Delphi
- •Синтаксис обробки виняткових ситуацій
- •Приклади обробки виняткових ситуацій
- •Виклик виняткової ситуації
- •Доступ до екземпляра об'єкта exception
- •3.4 Визначені оброблювачі виняткових ситуацій
- •3.4.1 Виключення, що виникають при роботі з базами даних
- •4 Графічні можливості delphi
- •Олівець і кисть
- •Олівець
- •Лістинг 4.1 Стилі заповнення областей
- •Вивід тексту
- •Методи креслення графічних примітивів
- •Лістинг 4.2 Осі координат і оцифрована сітка
- •Ламана лінія
- •Лістинг 4.3 Графік функції (використання методу Polyline)
- •Лістинг 4.4 Креслення замкнутого контуру (зірки) у точці натискання кнопки миші
- •Окружність і еліпс
- •Прямокутник
- •Багатокутник
- •Лістинг 4.5. Графік функції
- •Вивід ілюстрацій
- •Лістинг 10.6 Слайд-проектор
- •Бітові образи
- •Лістинг 4.7. Використання бітових образів
- •5 Робота з базами данних в delphi
- •Властивість sql
1.1. Складові класу
1. Поля
Полями називаються інкапсульовані в класі дані. Поля можуть бути будь-якого типу, у тому числі - класами, наприклад:
type TMyClass = class
aIntField: Integer;
aStrField: String;
aObjField: TObject;
end;
Кожен об'єкт одержує унікальний набір полів, але загальний для всіх об'єктів даного класу набір методів і властивостей. Фундаментальний принцип інкапсуляції вимагає звертатися до полів тільки за допомогою методів і властивостей класу. Однак у Object Pascal дозволяється звертатися до полів і прямо:
type
TMyClass = class
FIntField: Integer;
FStrField: String; end;
var
aObject: TMyClass;
begin
aObject.FIntField := 0;
aObject.FStrField := 'Рядок символів';
end;
Клас-нащадок одержує всі полючи усіх своїх предків і може доповнювати їх своїми, але він не може перевизначати їхній чи видаляти.
Таким чином, чим нижче в дереві ієрархії розташовується клас, тим більше даних одержують у своє розпорядження його об'єкти.
2. Методи
Инкапсульовані в класі процедури і функції називаються методами. Вони з'являються так само, як і звичайні підпрограми:
type
TMyClass = class
Function MyFunc(aPar: Integer): Integer;
Procedure MyProc;
end;
Доступ до методів класу, як і до його полів, можливий за допомогою складених імен:
var
aObject: TMyClass;
begin
aObject.MyProc;
end;
Як уже говорилося, методи класу можуть перекриватися в нащадках. Наприклад:
type
TParentClass = class Procedure DoWork;
end;
TChildClass = class(TParentClass) Procedure DoWork;
end;
Нащадки обох класів можуть виконувати подібну за назвою процедуру DoWork, але, у загальному випадку, будуть це робити по-різному. Таке заміщення методів називається статичним, тому що реалізується компілятором.
У Object Pascal набагато частіше використовується динамічне заміщення методів на етапі прогону програми. Для реалізації цей метод, що заміщається в батьківському класі, повинний з'являтися як динамічний (з директивою dynamic) чи віртуальний (virtual). Зустрівши таке оголошення, компілятор створить дві таблиці -DMT (Dynamic Method Table) і VMT (Virtual Method Table) і помістить у них адреси точок входу відповідно динамічних і віртуальних методів. При кожнім звертанні до методу, що заміщається, компілятор уставляє код, що дозволяє витягти адресу крапки входу в підпрограму з тієї чи іншої таблиці. У класі-нащадку метод, що заміщується, з'являється з директивою override (перекрити). Одержавши цю вказівку, компілятор створить код, що на етапі прогону програми помістив у батьківську таблицю точку входу методу класу-нащадка, що дозволить батьку виконати потрібну дію за допомогою нового методу.
Нехай, наприклад, батьківський клас за допомогою методів show і Hide відповідно показує чи ховає щось на екрані зображення. Для створення зображення він використовує метод Draw з логічним параметром:
type
TVisualObject = class(TWinControl)
Procedure Hide;
Procedure Show;
Procedure Draw(IsShow: Boolean); virtual;
end;
TVisualChildObject = class(TVisualObject)
Procedure Draw(IsShow: Boolean); override;
end;
Реалізація методів show і Hide дуже проста:
Procedure TVisualObject.Show;
begin
Draw(True) ;
end;
Procedure TVisualObject.Hide;
begin
Draw(False) ;
end;
Методи Draw у батька і нащадка мають різну реалізацію і створюють різні зображення. У результаті батьківські методи show і Hide - ховати чи показувати ті чи інші зображення будуть у залежності від конкретної реалізації методу Draw у-кожного зі своїх нащадків. Динамічне зв'язування повною мірою реалізує поліморфізм класів.
Різниця між динамічними і віртуальними методами полягає в тому, що таблиця динамічних методів DMT містить адреси тільки тих методів, що оголошені як dynamic у даному класі, у той час як таблиця VMT містить адреси віртуальних методів не тільки даного класу, але і всіх його батьків. Значно більше по розмірі таблиця VMT забезпечує більш швидкий пошук, у той час як при звертанні до динамічного методу програма спочатку переглядає таблицю DMT в об'єкта, потім -у його батьківського класу і так далі, поки не буде знайдена потрібна крапка входу.
Методи, що динамічно перекриваються, часто можуть узагалі нічого не робити. Такі методи називаються абстрактними, вони зобов'язані перекриватися в нащадках. Програміст може заборонити виклик абстрактного методу, оголосивши його з директивою abstract. Наприклад:
type
TVisualObject = class(TWinControl)
Procedure Draw(IsShow: Boolean); virtual; abstract;
end;
TVisualChildObject = class(TWinControl)
Procedure Draw(IsShow: Boolean); override; end;
var
aVisualObject: TVisualObject;
aVisualChild: TVisualChildObject ;
begin
aVisualObject.Show; {Помилка/ Звертання до абстрактного методу} aVisualChild.Show; {Нормальне звертання. Метод Draw у класу TVisualChildObject перекритий.)
end;
Звертання до неперекритого абстрактного методу викликає помилку періоду виконання. Зрозуміло, у грамотно складеній програмі абстрактні методи ніколи не викликаються. Класи, що містять абстрактні методи, називаються абстрактними. Такі класи інкапсулююють загальні властивості своїх неабстрактних нащадків, але об'єкти абстрактних класів ніколи не створюються і не використовуються. Для експлуатації абстрактних класів у бібліотеку класів Delphi включаються класи-нащадки, у яких перекриваються абстрактні методи батька.
До складу будь-якого класу входять два спеціальних методи -конструктор і деструктор. У класу TObject ці методи називаються create і Destroy, так само вони називаються в переважній більшості його нащадків. Конструктор розподіляє об'єкт у динамічній пам'яті і поміщає адресу цієї пам'яті в перемінну self, що автоматично з'являється в класі. Деструктор видаляє об'єкт із купи. Звертання до конструктора повинне випереджати будь-яке звертання до полів і деяких методів об'єкта. За своєю формою конструктори і деструктори є процедурами, але з'являються за допомогою зарезервованих слів constructor і Destructor:
type
TMyClass = class IntField: Integer; Constructor Create(Value: Integer);
Destructor Destroy;
end;
Будь-які поля об'єкта, а також методи класу, що оперують з його полями, можуть викликатися тільки після створення об'єкта за допомогою виклику конструктора, тому що конструктори розподіляють об'єкт у динамічній пам'яті і роблять дійсним покажчик, що міститься в об'єкті.
var
MyObject: TMyClass;
begin
MyObject.IntField := 0;
{ Помилка! Об'єкт не створений конструктором!}
MyObject := TMyClass.Create;
// Треба так: створюємо об'єкт
MyObject.IntField := 0;
// і звертаємося до його поля
MyObect.Free;
// Знищуємо непотрібний об'єкт
end;
У базовому класі TObject визначений метод Free, що спочатку перевіряє дійсність адреси об'єкта і лише потім викликає деструктор Destroy. Звертання до деструктора об'єкта буде помилковим, якщо об'єкт не створений конструктором, тому для знищення непотрібного об'єкта варто викликати метод Free, як це зроблено в попередньому прикладі.
Більшість конструкторів реалізують деякі дії, необхідні для правильної роботи об'єкта. Тому в конструкторі класу-нащадка варто спочатку викликати конструктор свого батька, а вже потім здійснювати додаткові дії. Виклик будь-якого методу батьківського класу досягається за допомогою зарезервованого слова inherited (успадкований):
Constructor TMyClass.Create(Value: Integer);
// Можлива реалізація конструктора
begin
Inherited Create; // Викликаємо успадкований конструктор IntField := Value; // Реалізуємо додаткові дії
end;
Деякі методи можуть викликатися без створення й ініціації об'єкта. Такі методи називаються методами класу, вони з'являються за допомогою зарезервованого слова class:
type
TMyClass = class(TObject)
class Function GetClassName: String;
end;
var
S: String;
begin
S := TMyClass.GetClassName;
end;
Методи класу не повинні звертатися до полів, тому що в загальному випадку викликаються без створення об'єкта, а отже, у момент виклику полів просто не існує. Звичайно вони повертають службову інформацію про клас - ім'я класу, ім'я його батьківського класу, адреса методу і т.п.
