Поліморфізм – це можливість використовувати однакові імена для методів, що входять в різні класи. концепція поліморфізму забезпечує з разі застосування методу до об’єкта використання саме того методу, який відповідає класу об’єкта.
Нехай визначені три класу, один з яких є базовим для двох інших:
tуре // базовий клас TPerson = class fname: string; // ім'я constructor Create (name : string); function info: string; virtual; end; // похідний від TPerson TStud = class (TPerson) fgr: integer; // номер навчальної трупи constructor Create (name: string; gr: integer); function info: string; override; end; // похідний від TPerson TProf = class (TPerson) fdep: string; // назва кафедри constructor Create (name : string; dep: string); function info: string; override; end;
У кожному з цих класів визначено метод info. У базовому класі за допомогою директиви virtual метод info оголошений віртуальним. Оголошення методу віртуальним дає можливість дочірньому класу зробити заміну віртуального методу своїм власним. У кожному дочірньому класі визначений свій метод info, який заміщає відповідний метод батьківського класу (метод породженого класу, що заміщає віртуальний метод батьківського класу, позначається директивою override).
Нижче наведено визначення методу info для кожного класу.
function TPerson.info: string; begin result : = ''; end; function TStud.info: string; begin result : = Fname + 'гр.' + IntTostr (fgr); end; function TProf.info:string; begin result : = Fname + 'каф.' + Fdep; end;
Так як обидва класу породжені від одного і того ж базового, оголосити список студентів і викладачів можна так (тут слід згадати, що об’єкт – це покажчик):
list: array [l . .SZL] of TPerson;
Оголосити подібним чином список можна тому, що мова Delphi дозволяє вказівником на батьківський клас привласнити значення покажчика на дочірній клас. Тому елементами масиву list можуть бути як об’єкти класу TStud, так і об’єкти класу TProf.
Вивести список студентів і викладачів можна застосуванням методу info до елементів масиву. наприклад, так:
st : = ''; for i: = l to SZL do // SZL - розмір масиву-списку if list [i] про NIL then st: = st + list [i] .Info + # 13; ShowMessage (st);
Під час роботи програми кожен елемент масиву може містити як об’єкт типу xstud, так і об’єкт типу TProf. Концепція поліморфізму забезпечує застосування до об’єкту саме того методу, який відповідає типу об’єкта.
Наступна програма, використовуючи розглянуті вище оголошення класів TPerson, TStud і TProf, формує і виводить список студентів і викладачів. Текст програми приведений в лістингу 9.1, а діалогове вікно – на рис. 9.1.
Рис. 9.1. Діалогове вікно програми Поліморфізм
Лістинг 9.1. демонстрація поліморфізму
unit polimor_; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = Class (TForm) Edit1: TEdit; Edit2: TEdit; GroupBoxl: TGroupBox; RadioButton1: TRadioButton; RadioButton2: TRadioButton; Label1: TLabel; Label2: TLabel; Button1: TButton; Button2: TButton; procedure ButtonlClick (Sender: TObject); procedure Button2Click (Sender: TObject); private { Private declarations} public { Public declarations} end; type // базовий клас TPerson = class fName: string; // ім'я constructor Create (name : string); function info: string; virtual; end; // клас Студент TStud = class (TPerson) fGr: integer; // номер групи constructor Create (name: string; gr: integer); function info: string; override; end; // клас Викладач TProf = class (TPerson) fdep: string; // назва кафедри constructor Create (name : string; dep: string); function info: string; override; end; const SZL = 10; // розмір списку var Forml: TForm1; List: array [l..SZL] of TPerson; // список n: integer = 0; // кількість людей в списку implementation {$ R * .DFM} constructor TPerson.Create (name: string) ; begin fName : = Name; end; constructor TStud.Create (name: string; gr: integer) ; begin inherited create (name); // викликати конструктор базового класу fGr : = Gr; end; constructor TProf.create (name: string; dep: string); begin inherited create (name); // викликати конструктор базового класу fDep : = Dep; end; function TPerson.Info : string; begin result : = Fname; end; function TStud.Info:string; begin result : = Fname + 'rp.' + IntToStr (fGr); end; function TProf.Info:string; begin result : = Fname + 'каф.' + FDep; end; // клацання на кнопці Додати procedure TForml.ButtonlClick (Sender: TObject); begin if n < SZL then begin // додати об'єкт до списку n: = n + l; if Radiobuttonl.Checked then // створимо об'єкт TStud List [n]: = TStud.Create (Edit1.Text, StrToInt (Edit2.Text )) else // створити об'єкт TProf List [n]: = TProf.Create (Edit1.Text, Edit2.Text); // очистити поля введення Edit1.Text : = ''; Edit2.Text: = ''; Edit1.SetFocus; // курсор в поле Прізвище end else ShowMessage ( 'Список заповнений!'); end; // клацання на кнопці Список procedure TForm1.Button2Click (Sender: TObject); var i: integer; // індекс st: string; // список begin for i: = 1 to SZL do if list [i] <> NIL then st: = st + list [i] .info + 113; ShowMessage ( 'Cпіcoк' + # 13 + st); end; end.
Процедура TForml.Buttoniciick, яка запускається натисканням кнопки Додати (Buttonl), створює об’єкт iist [n] класу TStud або TProf. Клас створюваного об’єкту визначається станом перемикача RadioButton. Установка перемикача в положення студент (RadioButtoni) визначає клас TStud, а в положення викладач (RadioButton2) – клас TProf.
Процедура TForm1.Button2Сlick, яка запускається натисканням кнопки Список (Button2), застосовуючи метод info до кожного об’єкту списку (елементу масиву), формує рядок, що представляє собою весь список.