Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
OЗП в delphi.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
105.77 Кб
Скачать

12.4. Поліморфізм. Віртуальні та динамічні методи

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

Усі методи, які розглядалися є статичними. При зверненні до статичного методу компілятор точно знає клас, до якого належить даний метод. Тому, наприклад, звернення до статичного методу GetPercentFree у методі CheckStatus компілюється у виклик TResourceGauge.GetPercentFree

Procedure TResourceGauge.CheckStatus;

begin

if GetPercentFree<=FPercentCritical then

Beep;

(TResourceGauge.GetPercentFree)

end;

Метод CheckStatus буде неправильно працювати у спадкоємцях TDiskGauge та TMemoryGauge, так як у цих класах метод GetPercentFree перекритий тому він не буде виконуватися. Звичайно, у класах TDiskGauge та TMemoryGauge метод CheckStatus можна було б продублювати, але при цьому втрачаються всі переваги успадкування. Ця проблема вирішується по іншому – метод GetPercentFree оголошується віртуальним за допомогою ключового слова virtual

Type

TResourceGauge=class

. . . . . .

Function GetPercentFree:integer; virtual;

. . . . . .

end;

У породжених класах віртуальний метод перекривається за допомогою ключового слова override

Type

TDiskGauge=class(ResourceGauge)

. . . . . .

Function GetPercentFree:integer;override;

. . . . . .

end;

TMemoryGauge=class(ResourceGauge)

. . . . . .

Function GetPercentFree:integer;override;

. . . . . .

end;

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

Віртуальний метод викликається по фактичному типу екземпляру а не по формальному записаному у програмі

Procedure TResourceGauge.CheckStatus;

begin

if GetPercentFree<=FPercentCritical then

Beep;

(<Фактичний клас>.GetPercentFree)

end;

Тому після зроблених змін метод CheckStatus у спадкоємцях TDiskGauge та TMemoryGauge буде працювати вірно.

Різновидністю віртуальних методів є динамічні методи, при їх оголошенні замість слова virtual використовується ключове слово dynamic

Type

TResourceGauge=class

. . . . . .

Function GetPercentFree:integer; dynamic;

. . . . . .

end;

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

Зустрівши оголошення динамічного або віртуального методу компілятор створить дві таблиці - DMT {Dynamic Method Table) і VMT {Virtual Method Table) і помістить у них адреси точок входу відповідно динамічних і віртуальних методів. При кожному звертанні до перекритого методу компілятор вставляє у програму код, що дозволяє вибрати адресу точки входу в підпрограму з тієї або іншої таблиці.

Різниця між динамічними й віртуальними методами полягає у тому, що таблиця динамічних методів DMT містить адреси тільки тих методів, які оголошені як dynamic у даному класі, а таблиця VMT містить адреси метолів оголошених як virtual не тільки даного класу, але й всіх його батьків. Вона значно більша за розміром ніж таблиця DMT і забезпечує більш швидкий пошук, у той час як при звертанні до динамічного методу програма спочатку переглядає таблицю DMT об'єкту, а потім - у його батьківського класу й так далі, поки не буде знайдена потрібна точка входу.

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

Type TResourceGauge=class

. . . . . .

Function GetPercentFree:integer;dynamic; abstract;

. . . . . .

end;

У класі TResourceGauge метод GetPercentFree повертає значення Result:=0; Звернення до таких метолів неможливе, вони виступають, як заготовки для створення інших кпасів.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]