end;
PCivil = ^TCivil; { указатель на объект «ГРАЖДАНСКИЙ СЛУЖАЩИЙ» }
TCivil = object (TPerson)
mLevel : integer; { должностная категория }
constructor Init(aBearing: integer; const aName, aFam : string;
aLevel: integer);
procedure Report;
end;
{--- Реализация объекта «ВОЕННОСЛУЖАЩИЙ» ---}
constructor TMilitary.Init(aBearing: integer; const aName, aFam,
aRank : string);
begin
mRank:= aRank;
end;
procedure TMilitary.Report;
begin
Writeln('Звание: '+mRank);
end;
{--- Реализация объекта «ГРАЖДАНСКИЙ СЛУЖАЩИЙ» ---}
constructor TCivil.Init(aBearing: integer; const aName, aFam : string;
aLevel: integer);
begin
mLevel:= aLevel;
end;
procedure TCivil.Report;
begin
Writeln('Категория: ', mLevel);
end;
var Persons : array[1..3] of PPerson; { массив указателей на ПРЕДКА }
i : integer;
begin {--- Главная программа ---}
{ Массив заполняется объектами РАЗНЫХ, но родственных типов }
Persons[1]:= New(
Persons[2]:= New(
Persons[3]:= New(
{ В ходе распечатки вызывается метод ФАКТИЧЕСКОГО объекта }
for i:=1 to 3 do Persons[i]^.Report;
Readln;
end.
Объяснять ли вам, из чего строят современные программы? Из сотен «умных» объектов, которые образуют ветвистую иерархию родственных связей, открывающую простор полиморфизму.
Многие объекты фирменных библиотек – это полуфабрикаты, требующие лишь небольшой настройки под конкретное применение. В ходе такой настройки программист добавляет к базовому объекту свои поля и методы. И здесь порой случается то же, что при использовании библиотечных модулей: имя, назначенное программистом, может совпасть с уже объявленным именем в предке. И тогда имена могут конфликтовать. В библиотечных модулях эта проблема решается скрытием большей части переменных, процедур и функций в невидимой извне секции реализации IMPLEMENTATION.
Схожий прием используют и в объектном программировании. Поля и методы, доступ к которым наследникам не нужен, прячут в объекте-предке так, что они становятся невидимыми за пределами предка. И тогда спрятанные имена можно использовать в наследниках повторно по иному назначению. Не будет ли здесь путаницы? Нет, поскольку методы предка не знают о новых именах и обращаются к старым. А методы наследника не видят старых имен и обращаются к новым. Разумеется, что разработчик объекта-предка тщательно отбирает те поля и методы, что потребуются создателям потомков.
Сокрытие имен объекта организовано очень просто: в объявление объекта вставляют ключевые слова PRIVATE (личный) и PUBLIC (общедоступный). Эти слова разбивают объявление объекта на две части – приватную и общедоступную, например:
type TParent = object { объект–предок }
A, B : integer;
function Calc(arg: integer): integer;
Constructor Init(a, b : integer)
function GetSum: integer; virtual;
end;
Здесь поля A и B, а также функция Calc, скрыты от взоров потомков. Поэтому программист, импортировавший объект типа TParent, может спокойно добавить в него свои поля или методы с теми же самыми именами, например, так:
type TChild = object (
A, B : string;
procedure Calc;
...
end;