procedure TMilitary.Report;
begin
inherited Report; { вызов метода предка }
Writeln('Воинское звание: '+mRank);
end;
Породив «военного человека», возьмёмся за мирное строительство, создадим объект, исполняющий роль гражданского служащего. Назовем его TCivil, а род его пойдет от того же предка TPerson. У гражданских своя гордость и своя служебная лестница, ступеньки которой – категории – нумеруются числами. Хранить информацию о карьерном росте будем в числовом поле, назовем его mLevel – «уровень». Так же, как и для военного, нам придется дополнить конструктор объекта и метод распечатки Report. Ход рассуждений будет прежним, а потому не буду повторять его, сделайте эту работу сами.
Сотворив наследников «человека» – объекты TMilitary и TCivil, мы почти разобрались в механизме наследования. А где же полиморфизм? В чем он проявляется? Для ответа обратимся к динамическим объектам.
Динамические переменные знакомы нам с 52-й главы. Указатели на объекты ничем не отличаются от таковых для других типов данных. Например, указатель на тип TPerson объявляется так:
type PPerson = ^TPerson;
Теперь можно объявить переменную этого типа, взять для неё память в куче, а затем инициализировать поля конструктором.
var P : PPerson; { указатель на объект }
begin
New(P); { выделение памяти в куче }
P^.Init(1985, 'Иван', 'Грозный'); { инициализация объекта }
В серьезных программах объекты обычно используют динамически, а выделение памяти и инициализацию выполняют там на каждом шагу. Потому в Паскаль введена функция New, совмещающая эти действия. Функция New подобна процедуре New, но вдобавок вызывает ещё и конструктор объекта. Функция принимает два странных параметра: тип-указатель на объект и конструктор этого объекта, а возвращает указатель на созданный объект. Так, динамический объект типа TPerson может быть порожден и инициализирован одним оператором.
P:= New(
Обратите внимание, что первый параметр функции – это тип-указатель PPerson, а не тип объекта TPerson!
var P : TPerson; { это указатель на объект! }
...
P:= TPerson.Init(1985, 'Иван', 'Грозный'); { создается динамический объект }
Дело в том, что все объекты в Delphi – это динамические переменные, и переменная типа TPerson является указателем на объект. Для создания таких объектов применяют не функцию New, а вызов конструктора с префиксом, совпадающим с названием типа объекта.
Теперь, после знакомства с динамическими объектами, вернемся к полиморфизму. Предположим, что в программе объявлены указатели трех типов.
var P1 : PPerson; { указатель на предка }
P2 : PMilitary; { указатель на потомка }
P3 : PCivil; { указатель на потомка }