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