Расширения ООП
TMT Паскаль осуществляет программирование объектно-ориентированных
расширений (OOП), подобных OOП расширениям в Borland Паскале. Эти
разделы описывают применяемый синтаксис OOP.
Объект
Наследование
Синтаксис Объекта
Ограничения На Описание Объекта
Область действия OOP
Описания Public и Private
Виртуальные методы
Конструкторы
Процедура Fail
Использование процедуры New (OOP)
Деструкторы
Зарезервированное слово Inherited
Параметр Self
Объект
Объект - структура, которая состоит из полей и методов. Поля - это
описание данных, в то время как методы определяют процедуры, которые
работают с данными. Объектные типы допускают четыре типа процедур:
процедуры, функции, а также конструкторы и деструкторы; последние два
допускаются только в пределах объектов.
См. также:
Синтаксис Объекта
Наследование
Один объектный тип может расширять другой объектный тип. Для этого добавляют или
заменяют поля и методы старого объекта. В этом случае новый объект называют
"объект-потомок"; старый объект называют "объект-предок". Процесс
расширения называется наследованием. Объектный тип потомка может иметь
своих собственных потомков; они также рассматриваются как потомки
первоначального объекта-предка. Область действия объекта - это объект вместе
со всеми его потомками.
Синтаксис Объекта
Синтаксис описания объектного типа
object [Наследие]
Список компонентов
[ предварительный список компонентов ]
end
где
Список компонентов определяется как:
[СписокПолей]
[СписокМетодов]
Наследие:
(Идентификатор объектного типа)
СписокПолей:
[ Вход поля [; Список полей ] ]
Вход поля:
Идентификатор списка : тип
СписокМетодов:
[ Вход метода [;СписокМетодов ] ]
Вход метода:
[ Заголовок метода[; virtual ] ]
Ограничения на описание Объекта
Объектные типы могут быть объявлены всюду, где идентификатор типа
позволяется синтаксисом Паскаля. Объектные типы могут быть объявлены в
пределах процедур, функций или других методов, если описание является однозначным.
Подобно записям, объектные типы не могут включать в себя Файлы, либо
записи или объекты, которые включают в себя файлы.
Область действия OOP
Составляющие объект идентификаторы доступны из всех методов во всей области
действия объекта, включая процедуры, функции, деструкторы и конструкторы,
которые осуществляют методы объекта и его потомков. Однако,
возможности полей и методов, объявленных в разделе
private описания
объектного типа ограничены модулем, который содержит определение объектного типа.
Поля и методы, объявленные разделе
private, недоступны из других модулей. К этим
полям и методам можно, однако, обращаться из других объектных типов,
объявленных в том же самом модуле. Ниже приведены примеры нескольких объектов:
type Point =
record
X,Y: Longint;
end
type Circle =
object
Center: Point;
Radius: Longist;
procedure Show;
procedure Hide;
end;
type Ellipse =
object (Circle)
Radius2: Longint;
Angle: Real;
procedure Show;
procedure Rotate(NewAngle: Real);
end;
Здесь тип объекта
Ellipse наследует поля
Center и
Radius от
Circle. Он также добавляет новые поля
Radius2
и
Angle. Кроме того, он использует метод
Hide
унаследованный от
Circle; он отменяет метод
Show и
добавляет новый метод
Rotate. Описание файла объекта включает
только заголовки методов. Сами методы должны появиться где-нибудь в
пределах текущей области действия. Таким образом, описания методов
подобны предварительно объявленным процедурам. Когда определено,
названия методов точно соответствуют названиям объекта. Например
procedure Circle.Draw;
begin
Graph.Circle(X,Y,Radius);
end;
Обратите внимание, что в пределах описания метода поля объекта видимы
для компилятора.
Описания Public и Private
Public и
private - стандартные директивы на языке
Объект-Паскаль. Обрабатываются они как зарезервированные слова. Для
удобочитаемости лучше организовать описание объекта видимым, помещая
все члены раздела
private вместе, сопровождая их всеми
членами
protected, и так далее. В этом случае каждое зарезервированное слово
видимости появляется не более одного раза и отмечает начало нового
раздела описания. Так что типовое описание объекта должно выглядеть
следующим образом:
type
TObject = object
private
{ Частные описания }
public
{ Общедоступные описания }
end;
Область действия идентификаторов, объявленных в
разделах
private ограничена модулем, который содержит описание
типа объекта. Имейте в виду что:
Внутри модуля идентификаторы, составляющие раздел private, действуют подобно нормальным идентификаторам раздела рublic.
За пределами модуля идентификаторы, составляющие раздел private неизвестны и недоступны.
Используйте часть
рublic для
Объявления полей данных, методов в объекте, к которым Вы хотите обратиться из других модулей
Объявления методов для доступа в других модулях
Описания в части
private ограничены в их доступе. Если Вы объявляете
поля или методы в разделе
private, то они являются неизвестными
и недоступными для внешних модулей, в которых определен объект. Используйте часть
private для
Объявления данных для доступа только в текущем модуле
Объявления методов для доступа только в текущем модуле
Виртуальные методы
Методы могут быть или статическими или виртуальными. Запросы к
статическим методам решаются при компиляции. Запросы к виртуальным методам
решаются во время выполнения с отсроченным или последующим связыванием.
По умолчанию методы статические; виртуальные методы содержат
специальное ключевое слово
virtual, которое является частью их описания.
Статические методы могут быть отменены без ограничений. Однако,
виртуальная отмена метода должна быть сделана методом, который
использует точно тот же самый синтаксис, например имеет те же самые
количество и типы аргументов. Объекты, которые содержат виртуальные
методы, требуют формирования специальной jump-таблицы, называемой
Виртуальной Таблицей Метода (VMT). VMT создается в течение инициализации
объекта через вызов конструктора.
Конструкторы
Конструкторы инициализируют объекты, создавая и
заполняя их VMT. Любой объект, который использует виртуальные методы,
должен быть сначала инициализирован.
type Circle =
object
Center: Point;
Radius: Longint;
constructor Init(Z:Point; R:Longint);
procedure Show; virtual;
procedure Hide;
destructor Kill;
end;
var
C: Circle;
P: Point;
Следующий код инициализирует, отображает, скрывает и отображает круг C:
P.X:=20;
P.X:=40;
C.Init(P,100);
C.Show;
While Not KeyPressed Do;
C.Hide;
C.Kill;
где:
constructor Circle.Init(Z:Point; R:Longint);
begin
Center:=P;
Radius:=R;
end;
Помимо инициализации полей круга
C; C.Init также создает
VMT таблицу. Эта таблица необходима, чтобы вызвать виртуальный метод,
такой как
Show.
Без вызова
C.Init вышеуказанный пример будет неработоспособен (вероятно
причинит исключение во время выполнения или остановит систему).
Однако если пример компилируется с включенной проверкой диапазона
{$R+}, TMT Паскаль автоматически обнаружит запросы от
непроинициализированного метода и произведет ошибку во время выполнения
программы.
См. также:
Процедура Fail
Деструкторы
Процедура Fail
Вызванная изнутри конструктора, процедура
Fail заставляет конструктор
освободить динамический объект, который она только что определила.
Описание:
procedure Fail;
Замечания:
Процедура
Fail должна вызываться только в том случае, если одна из операций
конструктора выполняется неудачно.
Использование процедуры New (OOP)
В большинстве случаев инициализация объекта объединена с распределением
памяти для объекта:
var C: ^Circle;
begin
New(C);
C.Init(P, R);
...
Расширенный синтаксис процедуры
New позволяет объединять
операцию:
var C: ^Circle;
begin
New(C.Init(P, R));
...
Обратите внимание, что конструкторы не могут быть виртуальными
методами, так как виртуальные методы не могут вызываться прежде, чем
конструктор инициализирует VMT.
См. также:
New
Деструкторы
Деструкторы используются для очистки памяти после того, как объект больше
не нужен. В отличие от конструкторов, деструктор может быть виртуален.
Удаление объекта часто объединяется с освобождением его памяти с
процедурой
Dispose:
var C: ^Circle;
begin
New(C);
C.Init(P,R);
...
C.Kill;
Dispose(C);
end;
Если конструктор будет не в состоянии выполнить инициализацию (часто
из-за ее неспособности распределить память для структур,
присоединяемых к объекту), он может выполнить специальную системную
функцию
Fail. Fail сигнализирует TMT Паскалю, что нужно полностью
изменить все распределение объекта, который мог бы быть создан и
возвращает ноль в качестве значения указателя объекта.
Fail может
вызываться только в пределах конструкторов.
См. также:
Конструкторы
Зарезервированное слово Inherited
Inherited может использоваться для обозначения предка метода
приложения объектного типа.
Inherited не может использоваться в
пределах методов типа объекта, который не имеет никакого предка.
Параметр Self
Методы имеют дополнительный неявный параметр, называемый
Self,
который автоматически встраивается компилятором.
Self содержит
пример объекта, для которого метод вызывался.
Self весьма полезен,
поскольку все его поля автоматически добавляются к символьной таблице
метода.