9.1 Инициализация |
Предыдущая Содержание Следующая |
Описания классов — долгоживущие объекты. Они постоянны и существуют практически так же долго, как приложение выполняется. Такие объекты по возможности инициализируются во время компиляции. Однако в главе 6 мы решили, что статическая инициализация делает описания классов трудными для сопровождения: порядок компонентов структур должен быть согласован со всеми инициализациями, а наследование вынудило бы нас раскрыть динамически компонуемые методы за пределами их файлов реализации. Для начальной загрузки мы инициализируем во время компиляции только описания Object и Class как статические структуры в файле Object.dc. Все другие описания классов генерируются динамически, а конструкторы метаклассов, начиная с Class_ctor(), заботятся о наследовании и перезаписи динамически компонуемых методов. ooc генерирует функции инициализации, чтобы скрыть детали вызова new() для генерации описаний классов, но факт того, что они должны явно вызываться в коде приложения, является источником трудно диагностируемых ошибок. Например, рассмотрите initPoint() и initCircle() из раздела 6.10:
void initPoint (void) { if (! PointClass) PointClass = new(Class, "PointClass", Class, sizeof(struct PointClass), ctor, PointClass_ctor, 0); if (! Point) Point = new(PointClass, "Point", Object, sizeof(struct Point), ctor, Point_ctor, draw, Point_draw, 0); }
Эта функция разработана, чтобы выполнить свою работу лишь однажды, то есть даже если она будет вызвана несколько раз, она создаст только один экземпляр каждого описания класса.
void initCircle (void) { if (! Circle) { initPoint(); Circle = new(PointClass, "Circle", Point, sizeof(struct Circle), ctor, Circle_ctor, draw, Circle_draw, 0); } }
Обе функции неявно соблюдают иерархию классов: initPoint() удостоверяется, что PointClass существует, прежде чем использовать его для генерации описания Point; вызов initPoint() в initCircle() гарантирует, что описание суперкласса Point и его описание метакласса PointClass существуют, прежде чем они будут использованы для генерации описания Circle. Опасности рекурсии нет: initCircle() вызывает initPoint(), потому что Point это суперкласс Circle, но initPoint() не будет ссылаться на initCircle(), потому что ooc не разрешает циклы в отношениях между суперклассами. Однако, всё пойдёт ужасно неправильно, если мы когда-нибудь забудем проинициализировать описание класса до того, как будем его использовать. Поэтому в этой главе мы рассмотрим механизмы, которые автоматически предотвратят эту проблему.
|
Предыдущая Содержание Следующая |