The website "dmilvdv.narod.ru." is not registered with uCoz.
If you are absolutely sure your website must be here,
please contact our Support Team.
If you were searching for something on the Internet and ended up here, try again:

About uCoz web-service

Community

Legal information

7.5 Возвращаемся к Object

7.5 Возвращаемся к Object

Предыдущая  Содержание  Следующая V*D*V

В разделе 7.1 мы увидели, что для того, чтобы работать с Point, необходимо собрать информацию для всех суперклассов по пути к корневому классу. Так как же определить Object? Конечно, не имело бы смысла определить Object как часть программы awk. Очевидный подход — написать файл описания класса:

 

#include <stdarg.h>

#include <stddef.h>

#include <stdio.h>

%prot

#include <assert.h>

 

% Class Object {

    const Class @ class;            // описание объекта

%

    void delete (_self);                // удалить экзмепляр

    const void * classOf (const _self); // класс объекта

    size_t sizeOf (const _self);        // размер объекта

%—

    void * ctor (_self, va_list * app); // конструктор

    void * dtor (_self);                // деструктор

    int differ (const _self, const Object @ b); // истина, если !=

    int puto (const _self, FILE * fp);  // вывести на экран

%}

 

К сожалению, это особый случай: будучи корневым классом Object не имеет суперкласса, а будучи первым метаклассом Class не имеет мета суперкласса. Только одно описание класса обладает этим свойством; поэтому, мы позволяем ooc распознавать этот специальный синтаксис для заголовка класса в качестве описаний классов `root и `metaroot.

Class представляет собой ещё одну проблему: мы видели в разделе 7.1, что новые метаклассы могут быть задекларированы напрямую с новым классом, так как они могут иметь в качестве новых компонентов только ссылки на методы. Class является первым метаклассом и имеет некоторые дополнительные компоненты:

 

% Class Class: Object {

   const char * name;                // имя класса

   const Class @ super;              // суперкласс класса

   size_t size;                      // занимаемый объектом размер памяти

%

   Object @ new (const _self, ...);  // создание экземпляра

   const void * super (const _self); // суперкласс класса

%}

 

Оказывается, что нашего синтаксиса описания классов вполне достаточно, чтобы описать Class. Это ещё один особый случай для ooc: это единственный класс, которому разрешено иметь в виде метакласса самого себя.

Если мы поместим оба описания в один файл описания класса Object.d и если позволим Object быть перед Class, поиск описаний классов в ooc будет заканчиваться сам по себе. Наша база данных завершена.

Мы могли бы написать реализацию Object и Class вручную — нет смысла в добавлении специального кода для ooc, если он используется только для генерации одной реализации. Тем не менее, наш механизм генерации отчётов достаточно хорош, чтобы быть адаптированным для Object, и мы можем получить значительную выгоду.

Файлы интерфейса для Point и Object очень похожи за исключением того, что Object.h не имеет интерфейса суперкласса для подключения и не декларирует функцию инициализации. Однако, соответствующий ему файл отчета h.rep используется много раз, так что мы должны избежать загромождения его условными операторами, которые обычно не нужны. Вместо этого мы добавим параметр в командной строке ooc:

 

$ ooc -R Object -h > Object.h

 

Этот параметр вызывает загрузку специального файла отчёта h−R.rep, который создан специально для корневого класса. Оба файла отчёта в основном генерируют заголовки методов и могут совместно использовать ещё один файл отчета header.rep, который содержит отчёт header, используемый в обоих случаях.

Аналогично, много общего имеют файлы представлений Point и Object и чтобы для учёта различий загрузить файл отчёта r-R.rep вместо r.rep мы используем -R:

 

$ ooc -R Object -r > Object.r

 

Object.r не имеет суперкласса представление для подключения, а структура метакласса для Class начинается с дополнительных компонентов. Общий код декларации селекторов суперклассов и методов, как  компонентов метакласса, находится в другом файле отчёта, va.rep.

Наконец, можно использовать -R и ещё один файл отчёта c-R.rep вместо c.rep, чтобы помочь сгенерировать данную реализацию:

 

$ ooc -R Object Object.dc > Object.c

 

ooc добавит операторы include и заголовки методов предварительной обработки в Object.dc как и в любой другой файл реализации. Единственное различие заключается в реализации %init: мы всё ещё можем позволить ooc сгенерировать селекторы и селекторы суперклассов, но мы должны закодировать статическую инициализацию описаний классов, показанных в разделе 6.7, вручную.

Существует вопрос, как следует написать конструктор метакласса Class_ctor(). Если мы сделаем это в Object.dc вручную, то по существу закодируем цикл для обработки пар селектор / метод дважды: один раз в Object.dc для Class_ctor() и один раз в файле отчета c.rep для всех других классов. Оказывается, у нас есть достаточно информации, чтобы сделать это в c-R.rep. Если мы предположим, что первые несколько аргументов конструктора появляются в тот же порядке, что и компоненты, указанные для Class, то сможем сгенерировать весь конструктор и таким образом использовать общий код цикла в качестве отчёта meta-ctor-loop в общем файле отчёта etc.rep.

 

Предыдущая  Содержание  Следующая