
- •Передмова
- •Розділ 1 об'єктний підхід у програмуванні
- •1.1.Причини виникнення ооп
- •1.1.1.Складність об'єкта дослідження
- •1.1.2.Складність процесу розробки програмного забезпечення
- •1.1.3.Складність опису окремих елементів
- •1.2.Парадигма ооп
- •1.3.Історія розвитку ооп
- •Розділ 2 об'єкти й класи: інкапсуляція
- •2.1.Структура об'єкта й класу
- •2.2.Особливості опису класів у мовах ооп
- •2.2.1.Опис класів в SmallTalk
- •2.2.3.Опис класів в Delphi
- •2.2.4.Опис класів в Java
- •2.3.Поля даних та їх ініціалізація
- •2.3.1.Визначення полів даних в SmallTalk
- •2.3.3.Визначення полів даних в Delphi
- •2.3.4.Визначення змінних в Java
- •2.4.Доступ до даних
- •2.4.1.Доступ до даних в SmallTalk
- •2.4.3.Доступ до даних в Delphi
- •2.4.4.Доступ до даних в Java
- •2.5.Спеціальні змінні
- •2.5.1.Спеціальні змінні в SmallTalk
- •2.5.3.Спеціальні змінні в Java
- •2.5.4.Спеціальні змінні в Delphi
- •2.6.Посилання
- •2.6.1.Визначення посилань в SmallTalk, Delphi і Java
- •2.7.Методи
- •2.7.1.Загальна схема визначення методу
- •2.7.2.Визначення методів в SmallTalk
- •2.7.4.Визначення методів в Delphi
- •2.7.5.Визначення методів в Java
- •2.8."Дружні" методи
- •2.8.2.Аналог дружніх функцій в Delphi
- •2.9.Конструктори й деструктори
- •2.9.1.Конструктори й деструктори в SmallTalk
- •2.9.3.Конструктори й деструктори в Delphi
- •2.9.4.Конструктори й деструктори в Java
- •2.10.Властивості
- •2.10.1.Властивості в Delphi
- •2.10.2.Властивості в Java
- •2.12.Абстрактні методи
- •Розділ 3 успадкування
- •3.1.Форми успадкування
- •3.2.Успадкування в SmallTalk
- •3.3.1.Віртуальне успадкування
- •3.3.2.Правило сумісності типів
- •3.3.3.Використання конструкторів і деструкторів при успадкуванні
- •3.4.Успадкування в Delphi
- •3.4.1.Ієрархія класів в Delphi
- •3.4.2.Створення нових компонентів
- •3.5.Успадкування в Java
- •3.5.1.Використання ключового слова super
- •3.5.2.Клас Object
- •Розділ 4 поліморфізм
- •4.1.Віртуальні методи
- •4.2.1.Механізм пізнього зв'язування
- •4.2.2.Таблиця віртуальних методів
- •4.3.Поліморфізм в Delphi
- •4.3.1.Заміщення віртуальних і динамічних методів
- •4.3.2.Приведення типів
- •4.4.Поліморфізм в Java
- •4.5.Поліморфізм в SmallTalk
- •5.1.Потокові класи
- •5.1.1.Ієрархія потокових класів
- •5.1.2.Форматоване введення/ виведення
- •5.1.3.Маніпулятори
- •5.1.4.Введення/виведення у файл
- •5.2.Контейнерні класи
- •5.2.1.Ітератори
- •5.2.2.Визначення контейнерних класів
- •5.2.3.Стандартні контейнерні класи
- •5.3.1.Параметиізовані класи (шаблони)
- •5.3.2.Ітератори stl
- •5.3.3.Узагальнені алгоритми
- •Література
- •Додатки лабораторна робота №1 об'єкти й повідомлення в smalltalk
- •Лабораторна робота №2 класи й методи в smalltalk
- •Листинг 3.1
- •Листинг 3.2
- •Листинг 3.3
- •Лабораторна робота 5 компоненти в delphi
- •Лабораторна робота 6 меню й вікна в delphi
- •Лабораторна робота 7 розробка меню в java
- •Лабораторна робота 8 робота з подіями в java
4.3.Поліморфізм в Delphi
В Delphi полиморфічними властивостями володіють методи, позначені як virtual або dynamic.
procedure MyProc1; virtual;
procedure MyProc2; dynamic;
Загальне для них полягає в тому, що при їхньому виклику здійснюється пізнє зв'язування, а різниця – у використовуваних таблицях: для virtual – це VMT, а для dynamic – DMT (Dynamic Method Table) таблиці. Різниця цих таблиць складається в наступному. В VMT зберігаються адреси всіх віртуальних методів класу, включаючи й методи суперкласу. А в DMT зберігаються адреси тільки тих динамічних методів, які описані в даному класі. Таким чином, virtual методи вимагають більше пам'яті, але швидше викликаються, dynamic методи вимагає менше пам'яті, але їхній пошук ускладнюється.
О
днак
ефективність по пам'яті в Delphi менш
критична в порівнянні з C++, тому що
VMT і DMT зберігаються в сегменті
коду, у той час, як VMT в C++
зберігаються в сегменті даних.
Структура об'єктів в Delphi з обліком VMT і DMT наведена на рис. 4.5.
Рис. 4.5. Структура об'єктів в Delphi з VMT і DMT
Поле RTTI (RunTimeType Information – інформація часу виконання) має приблизно наступний формат (формат RTTI не документується):
RTTI = record
vtDynamicTable : word; {покажчик на VMT}
vtClassName: word; {пок. на метод, що повертає ім'я класу}
vtInstSize : word; {пок. на метод, що повертає розмір екземпляра}
vtParent : word; {пок. на метод, що повертає предка}
vtNewInst : word; {конструктор}
vtFreeInst : word; {деструктор}
Оскільки RTTI властива класу, то вона може використовуватися для створення його екземпляра. Доступ до RTTI поза методами класу можна одержати, описавши покажчик на клас, тобто на RTTI:
type
TNewClass = class;
TClass = class of TNewClass;
Для основних класів ієрархії Delphi покажчики на них вже визначені за замовчуванням і мають вигляд:
TContlorClass
TComponentClass
Покажчики на клас підкоряються правилу приведення об'єктних типів: покажчик на клас-предок може посилатися на будь-який клас нащадок, але не навпаки.
Найважливіші методи класу визначені в TObject. Вони дозволяють витягти всю необхідну інформацію про клас:
сlass function ClassName: string; {ім'я класу}
сlass function ClassParent: TClass; {клас-предок}
сlass function InstanceSize: word; {розмір екземпляра}
Наприклад, якщо потрібно витягти ім'я класу, варто скористатися наступним кодом:
type
TMyClass = class;
TRefClass = class of TObject;
var
MyRef : TRefClass;
s: string;
begin
MyRef := TObject;
s := MyRef.ClassName; {s одержить значениеTObject}
MyRef := TMyRef;
s := MyRef.ClassName; {s одержить значення TMyRef}
end.
4.3.1.Заміщення віртуальних і динамічних методів
В Delphi метод предка заміщається в тому випадку, якщо для нього зазначена директива override. Якщо її не вказати, то метод не заміщається, тобто ланцюжок поліморфізму розривається:
Приклад 4.1:
type TFirst = class
procedure StatMethod;
procedure VirtProc1; virtual;
procedure VirtProc2; virtual;
procedure DynaProc1; dynamic;
procedure DynaProc2; dynamic;
procedure Broken; virtual;
end;
TSecond = class (TFirst)
procedure StatMethod; override; // помилка
procedure VirtProc1; virtual; // заміщення
procedure DynaProc1; dynamic; // заміщення
procedure Broken; virtual; // заміщення немає
end;
var
theObj1: TFirst;
theObj2: TSecond;
begin
theObj1:= TFirst.Create;
theObj2:= TSecond.Create;
……………………………
end......
Застосування override до статичного методу викликає помилку компіляції, а до віртуального й динамічного методу приводить до його заміщення. Якщо метод у класі-нащадку оголошується як віртуальний, то заміщення не відбувається, а створюється новий віртуальний метод і ланцюжок поліморфізму обривається.
Структура об'єктів для даного приклада наведена на рис 4.6:
Рис. 4.6. Структура об'єктів для приклада 4.1