- •X,y : real;
- •Virtual.
- •656535 И должен быть уникальным среди индексов других динамичес-
- •Inherited; в методах объектного типа, не имеющего предка, ключе-
- •Integer. Обратите внимание на использование в описаниях tCharVal
- •Глава 5. Переменные и типизированные константы
- •Value: 0; Min: -999; Max: 999);
- •Value: Direction;
Virtual.
B.Pascal 7 & Objects/LR - 56 -
Динамические методы
─────────────────────────────────────────────────────────────────
Borland Pascal поддерживает дополнительные методы с поздним
связыванием, которые называются динамическими методами. Динами-
ческие методы отличаются от виртуальных только характером их дис-
петчеризации на этапе выполнения. Во всех других отношениях дина-
мические методы считаются эквивалентными виртуальным.
Описание динамического метода эквивалентно описанию вирту-
ального метода, но описание динамического метода должно включать
в себя индекс динамического метода, который указывается непос-
редственно за ключевым словом virtual. Индекс динамического мето-
да должен быть целочисленной константой в диапазоне от 1 до
656535 И должен быть уникальным среди индексов других динамичес-
ких методов, содержащихся в объектном типе или его предках. Нап-
ример:
procedure FileOpen(var Msg: TMessage); virtual 100;
Переопределение динамического метода должно соответствовать
порядку, типа и именам параметров и точно соответствовать типу
результата функции порождающего метода. Переопределение также
должно включать в себя директиву virtual, за которой следует тот
же индекс динамического метода, который был задан в объектном ти-
пе предка.
Примечание: Подробнее о динамических методах и о раз-
нице в диспетчеризации динамических и виртуальных методов
рассказывается в Главе 22.
B.Pascal 7 & Objects/LR - 57 -
Создание экземпляров объектов
─────────────────────────────────────────────────────────────────
Экземпляр объекта создается посредством описание переменной
или константы объектного типа или путем применения стандартной
процедуры New к переменной типа указатель на объектный тип. Ре-
зультирующий объект называется экземпляром объектного типа.
var
F: TField;
Z: TZipField;
FP: PField;
ZP: PZipField;
С учетом этих описание переменных F является экземпляром
TField, а Z - экземпляром TZipField. Аналогично, после применения
New к FP и ZP, FP будет указывать на экземпляр TField, а ZP - на
экземпляр TZipField.
Если объектный тип содержит виртуальные методы, то экземпля-
ры этого объектного типа должны инициализироваться посредством
вызова конструктора перед вызовом любого виртуального метода. Ни-
же приведен пример:
var
S: StrField;
begin
S.Init (1, 1, 25, 'Первое имя');
S.Put ('Френк');
S.Display;
...
S.Done;
end;
Если S.Init не вызывался, то вызов S.Display приведет к неу-
дачному завершению данного примера.
Присваивание экземпляра объектного типа не подразумевает
инициализации экземпляра.
Объект инициализируется кодом, генерируемым компилятором,
который выполняется между вызовом конструктора, и когда выполне-
ние фактически достигает первого оператора в блоке кода конструк-
тора.
Если экземпляр объекта не инициализируется, и проверка диа-
пазона включена (директивой {$R+}), то первый вызов виртуального
метода экземпляра объекта дает ошибку этапа выполнения. Если про-
верка диапазона выключена (директивой {$R-}), то первый виртуаль-
ного метода неинициализированного объекта может привести к неп-
редсказуемому поведению.
Правило обязательной инициализации применимо также к экземп-
B.Pascal 7 & Objects/LR - 58 -
лярам, которые являются компонентами структурных типов. Например:
var
Comment: array [1..5] of TStrField;
I: integer;
begin
for I := 1 to 5 do
Comment [I].Init (1, I + 10, 40, 'первое_имя');
.
.
.
for I := 1 to 5 do Comment [I].Done;
end;
Для динамических экземпляров инициализация, как правило,
связана с размещением, а очистка - с удалением, что достигается
благодаря расширенному синтаксису стандартных процедур New и
Dispose. Например:
var
SP: StrFieldPtr;
begin
New (SP, Init (1, 1, 25, 'первое_имя');
SP^.Put ('Френк');
SP^.Display;
.
.
.
Dispose (SP, Done);
end;
Указатель на объектный тип является совместимым по присваи-
ванию с указателем на любой родительский объектный тип, поэтому
во время выполнения программы указатель на объектный тип может
указывать на экземпляр этого типа или на экземпляр любого дочер-
него типа.
Например, указатель типа ZipFieldPtr может присваиваться
указателям типа PZipField, PNumField и PField, а во время выпол-
нения программы указатель типа PField может либо иметь значение
nil, либо указывать на экземпляр TField, TNumField или TZipField,
или на любой экземпляр дочернего по отношению к TField типа.
Эти правила совместимости указателей по присваиванию приме-
нимы также к параметрам-переменным объектного типа. Например, ме-
тоду TField.Copy могут быть переданы экземпляры типов TField,
TStrField, TNumField, TZipField или любые другие экземпляры до-
чернего от TField типа.
B.Pascal 7 & Objects/LR - 59 -
Активизация методов
─────────────────────────────────────────────────────────────────
Метод активизируется посредством оператора вызова процедуры
или функции, состоящего из десигнатора метода, за которым следует
список параметров. Такой тип вызова называется активизацией мето-
да.
десигнатор метода
│ ┌────────────────────┐
└─┬──────────────────────────────────────>│идентификатор метода├>
│ ^ └────────────────────┘
│ ┌──────────────────────┐ ┌───┐ │
└>│ ссылка на переменную ├>│ . ├────┘
└──────────────────────┘ └───┘
Ссылка на переменную задается, если десигнатор метода должен
описывать экземпляр объектного типа, а идентификатор метода дол-
жен обозначать метод этого объектного типа.
Экземпляр, обозначенный десигнатором метода, становится не-
явным фактическим параметром метода; он соответствует формальному
параметру-переменной с именем Self, который владеет объектным ти-
пом, соответствующим активизированному методу.
Для статических методов описанный тип (на этапе компиляции)
определяет, какой из методов активизируется. Например, десигнато-
ры F.Init и FP^.Init всегда активизируют TField.Init, так как
описанным типом F и FP^ является TField.
Для виртуальных методов выбором экземпляра управляет факти-
ческий тип (этапа выполнения). Например, десигнатор FP^.Display
может активизировать методы TField.Display, TStrField.Display,
TNumField.Display или TZipField.Display (в зависимости от факти-
ческого типа экземпляра, указываемого FP).
В операторе with, ссылающемся на экземпляр объектного типа,
ссылка на переменную в десигнаторе метода может опускаться. В
этом случае экземпляром, на который ссылается оператор with, ста-
новится неявный параметр Self активизации метода. Аналогично,
ссылка не переменную может опускаться в методе. В этом случае
параметром Self метода, содержащего вызов, становится неявный па-
раметр Self активизации метода.
B.Pascal 7 & Objects/LR - 60 -
Активизация уточненных методов
─────────────────────────────────────────────────────────────────
В методе, операторе вызова функции или процедуры для обозна-
чения активизации конкретного метода допускается использование
десигнатора уточненного метода. Такой тип вызова называется акти-
визацией уточненного метода.
десигнатор уточненного метода
│ ┌──────────────────────┐ ┌───┐ ┌────────────────────┐
└─┬>│ идентификатор ├>│ . ├───────>│идентификатор метода├>
│ │ объектного типа │ └───┘ ^ └────────────────────┘
│ └──────────────────────┘ │
│ ┌──────────────────────┐ │
└>│ inherited ├──────────┘
└──────────────────────┘
Объектный тип, заданный в десигнаторе уточненного метода,
должен быть таким же, как и включающий метод объектный тип, или
соответствовать родительскому типу.
Для обозначения родительского объектного типа или объектного
типа, включающего метод, можно использовать ключевое слово
