0988b24c

Описание объектов


Описание объекта состоит из описаний структур данных объекта и описаний процедур метода, которые вы можете вызывать для данно- го объекта. Описание объекта не означает создание экземпляра объ- екта. Как это сделать, вы узнаете позднее.

Описание базового объекта

Когда вы описываете объект, Турбо Ассемблер создает структу- ру STRUC и описывает данные для этого объекта, и таблицу TABLE, которая описывает методы объекта. Описания данных объекта предс- тавляет собой структуру с тем же именем, что и объект. Описания методов объектов записывается в типе данных TABLE с именем @Table _<имя_объекта>.

Примечание: Более подробно о применении к описанию объ- ектов директивы STRUC рассказывается в Главе 8.

Например, для объекта списка два типа данных описываются следующим образом:

list STRUC описывает следующие элементы:

list_head указатель dword на начало списка list_tail указатель dword на конец списка

@Table_list TABLE описывает следующие методы:

construct указатель dword на процедуру list_construct destroy указатель dword на процедуру

list_destroy и т.д.

Директива STRUC описывает данные для объекта, которые созда- ются каждый раз, когда вы создаете экземпляр объекта. Директива TABLE описывает таблицу используемых по умолчанию для данного описания процедур метода. Турбо Ассемблер поддерживает этот тип данных, он не создает экземпляр таблицы где-либо в памяти прог- раммы. Однако позднее вы увидите, что экземпляр таблицы нужно включить для любого объекта, использующего виртуальные методы.

Приведем пример определений объекта для связанного списка:

list STRUC GLOBAL METHOD { destroy:dword = list_construct ; процедура-конструктор ; списка init:dword = list_init ; процедура-инициализа- ; тор списка deinit:dword = list_deinit ; процедура-деинициали- ; затор списка virtual insert:word = list_insert ; процедура вставки ; узла списка virtual append:word = list_append ; процедура добавле- ; ния узла списка virtual remove:word = list_delete ; процедура удале- ; ния узла списка virtual first:word = list_first ; процедура первого ; узла списка virtual last:word = list_last ; процедура последне- ; го узла списка } list_head dd ? ; указатель начала ; списка list_tail dd ? ; указатель конца ; списка


ENDS
Примечание: Ключевое слово METHOD показывает, что вы используете расширенную форму директивы STRUC и определяете объект с именем list (список).
Примечание: Каждая запись состоит из имени метода, двоеточия, размера указателя на процедуру метода (WORD для ближних процедур, DWORD для дальних процедур). Далее следу- ет символ равенства, имя процедуры и вызов этого метода.
Давайте возьмем данный пример и посмотрим, что происходит.
Ключевое слово METHOD указывает на вызов метода. За ним сле- дует описаний процедур метода для данного объекта. Поскольку спи- сок методов занимает более одной строки, описания заключаются в фигурные скобки ({ }).


Каждое описание метода сообщает Турбо Ассемблеру, какую про- цедуру ему следует использовать для работы с объектом при вызове имени данного метода.
Например, первое описание процедуры метода:
construct:dword = list_construct
объявляет метод с именем consrtruct, которая является процедурой дальнего типа (указатель в нее записывает DWORD). Фактическим именем процедуры метода является list_construct, что следует оп- ределить где-либо еще в исходном коде. Турбо Ассемблер рассматри- вает метод как виртуальный, если ему предшествует ключевое слово VIRTUAL. Когда вы вызываете такой метод, Турбо Ассемблер будет искать адрес процедуры метода, извлекая его из таблицы, которая присутствует в памяти во время загрузки. В противном случае метод является статическим методом. Это означает, что Турбо Ассемблер может определить его адрес на этапе компиляции. Например, метод construct является статическим методом, а метод insert описывает- ся как виртуальный метод. Позднее в этой главе мы поясним, для чего может понадобиться выбирать виртуальные или статические ме- тоды.
Далее за разделом описания процедуры метода непосредственно следует структура данных. Это определение использует синтаксис стандартной директивы STRUC. Данный пример содержит описания на- чала и конца списка.
В части описания метода в описании объекта, пока вы не ис- пользуете виртуальные методы, никаких данных в структуру данных объекта не заносится. Эти описания приводят к тому, что Турбо Ас- семблер будет строить отдельную таблицу структуры данных, которая содержит в качестве используемых по умолчанию значений адреса за- данных процедур метода. Для каждого объекта вы должны иметь эк- земпляр данной таблицы, и должны явно поместить таблицу. Как это сделать, мы поясним в данной главе позднее.


Так как описание должно присутствовать в модуле, содержащем процедуры метода для объекта (а также включаться в любой исполь- зующий объекты исходный код), вы должны описать сам объект в от- дельном файле, который может включаться (INCLUDE) в ваш исходный код.
Мы рекомендуем вам использовать имя файла в виде имя_объек- та.ASO (что означает ассемблируемый объект). В этот файл следует включать только описание объекта. Методы объекта следует разме- щать в другом исходном файле, благодаря чему вы можете включать описание объекта там, где это потребуется. Например, описание объекта связанного списка в предыдущем примере можно было бы раз- местить в файле LIST.ASO. Для определения процедур метода объекта можно использовать файл LIST.ASM. В любую программу, использующую объекты, можно было бы включить LIST.ASO, но не LIST.ASM.
Ключевое слово GLOBAL в описании объекта приводит к тому, что Турбо Ассемблер делает эту информацию общедоступной. Это поз- воляет вам использовать объект в модуле, отличном от того модуля, в котором он определен. Во все использующие объект модули должно включаться описание объекта.
Описание порожденного объекта
Объект, который наследует методы и данные другого объекта, называется порожденным (производным) объектом. Вы не можете пере- определить элементы структуры данных порождающего объекта, но мо- жете переопределить отдельные методы, задавая их в списке методов нового объекта.
Независимо от того, является ли объект базовым или порожден- ным от другого объекта, его может наследовать другой объект. Нас- ледуемый объект называется порождающим (родительским) объектом. Порожденный объект наследует данные и методы порождающего объек- та, поэтому вам следует использовать наследование только в тех случаях, когда эти методы и данные полезны для нового объекта.
Например, вы можете определить объект очереди, который нас- ледует объект связанного списка (поскольку очередь можно реализо- вать в виде связанного списка). Приведем пример такого порожден- ного объекта:


queue STRUC GLOBAL list METHOD { init:DWORD=queue_init virtual insert:word = queue_insert ; (процедура вставки ; узла очереди) virtual remove:word = queue_delete ; (процедура удаления ; узла очереди) virtual first:word = queue_first ; (процедура первого ; узла очереди) virtual last:word = queue_last ; (процедура послед- ; него узла очереди) virtual enqueue:word = list_append ; процедура постановки ; в очередь virtual dequeue:word = queue_dequeue ; процедура удаления ; из очереди
Размещение перед ключевым словом METHOD объекта с именем list (список) указывает Турбо Ассемблеру, что новый объект queue (очередь) наследует методы и данные объекта list. Размещенный в этом месте объект с любым именем будет наследоваться описываемым объектом. Допускается использовать только одно имя (поддерживает- ся только одиночное наследование).
Новый объект queue наследует все данные и методы объекта списка list (если вы их не переопределяете). Заметим, что в queue для установки указателя на таблицу виртуальных методов для очере- дей требуется своя собственная процедура init.
Наследуемые для очереди описания методов insert, remove, first и last вновь специфицируются в описании, поэтому данные ме- тоды заменяются указанными процедурами.
Для очереди описываются два новых метода: enqueue и dequeue. Заметим, что процедура метода для enqueue (добавление в конец очереди) представляет собой то же самое, что присоединение к кон- цу списка. Однако для извлечения из очереди (отмены постановки в очередь) нужна новая процедура, которая называется queue_dequeue.
Объект queue не содержит дополнительных данных, отличных от тех, которые наследуются из списка list. Он наследует указатели начала и конца связанного списка, которые для очереди также нуж- ны, поскольку методы связанного списка используются для обслужи- вания очереди.

Содержание раздела