З правил сумісності фактичних і формальних параметрів типу «об’єкт» випливає, що в якості фактичного параметра може виступати об’єкт будь-якого похідного типу від типу формального параметра. Таким чином, під час компіляції процедури невідомо, об’єкт якого типу буде їй переданий в якості фактичного параметра (такий параметр називається поліморфним об’єктом). Повною мірою поліморфізм об’єктів і методів реалізується за допомогою віртуальних методів.
Метод стає віртуальним, якщо після його визначення в типі об’єкта проставлене службове слово VIRTUAL.
PROCEDURE ІмяМетоду(параметри); VIRTUAL;
або
FUNCTION ІмяМетоду(параметри):ТипЗначення; VIRTUAL;
При віртуалізації методів повинні виконуватися наступні умови:
1. Якщо прабатьківський тип об’єкту описує метод як віртуальний, то всі його похідні типи, що реалізують метод з таким самим іменем, повинен описувати цей тип теж як віртуальний. Іншими словами, не можна заміняти віртуальний метод статичним. Якщо ж це трапиться, компілятор повідомить про помилку номер 149 VIRTUAL expected (очікується службове слово VIRTUAL)
2. Якщо перевизначається реалізація віртуального методу, то заголовок заново визначеного віртуального методу у похідному типі не може бути зміненим. Інакше кажучи, повинні залишатися незмінними порядок розміщення, кількість і типи формальних параметрів в однойменних віртуальних методах. Якщо цей метод реалізується функцією, то не може мінятися і тип результату. При зміні заголовку методу компілятор видасть повідомлення про помилку номер 131 Header does not match previous definition («Заголовок не відповідає попередньом визначенню»).
3. В описі об’єкту повинен обов’язково описуватися спеціальний метод, що ініціалізує об’єкт (звичайно його називають Init). В цьому методі службове слово PROCEDURE в оголошенні і реалізації повинне бути замінене на слово CONSTRUCTOR. Конструктор завжди викликається до першого виклику віртуального методу. Виклик віртуального методу без попереднього виклику конструктора може привести систему до тупикового стану, а компілятор не перевіряє порядку виклику методів. Пам’ятаймо про це! Об’єкт може мати кілька конструкторів. Конструктор є статичним методом.
Спробує розв’язати проблему успадковування, поставлену у попередньому підрозділі, з використанням віртуалізації методів (Програма 3.2).
program prakt1;
uses crt;
type
TStudent=object
Name:String[30];
Date:string[10];
rate:real;
constructor init(nm,Dt:String;rt:real);
function GetName:string; virtual;
function getdate:string;
function getrate:real;
procedure showname;
procedure showdate;
procedure showrate;
end;
TStudent1=object(TStudent)
Bal:real;
constructor init(nm,dt:string;rt,bl:real);
function getname:string;virtual;
function getbal:real;
function getsum:real;
procedure showbal;
procedure showall;
end;
constructor TStudent.init(nm,dt:string;rt:real);
begin
name:=nm;
date:=dt;
rate:=rt;
end;
function TStudent.GetName:string;
begin
getname:=name;
end;
procedure TStudent.showname;
begin
writeln(getname);
end;
constructor TStudent1.init(nm,dt:string;rt,bl:real);
begin
name:=nm;
date:=dt;
rate:=rt;
bal:=bl;
end;
function TStudent1.GetName:string;
begin
getname:=’~’+name+’~’;
end;
(далі йде текст всіх раніше створених методів)
var st:TStudent;
st1:TStudent1;
begin
clrscr;
writeln(‘батьківський обєкт’);
st.init(‘Ляшук’,’01.02.1995’,700);
st.showname;
writeln(‘спадкоємець’);
with st1 do begin
init(‘Panko’,’10.10.1995’,550,4.8);
showname;
end;
writeln(‘=======================’);
repeat until keypressed;
end.
Програма 3.2
Метод getname ми описали як віртуальний і це дало нам змогу по-справжньом використати поліморфізм. Виконавши програму, переконаємося, що поле name батьківського і дочірнього об’єкту виводяться дещо по-різному:
