6.11 Выводы

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

Объекты указывают на описания своих классов, которые по большей части содержат указатели на динамически скомпонованные методы. Описания классов с одним и тем же набором указателей методов образуют метакласс — описания классов тоже объекты. Метакласс, опять-таки, имеет описание класса.

Всё имеет предел, поскольку мы начинаем с простого класса Object и с первого метакласса Class, который имеет Object в качестве суперкласса. Если тот же набор методов — конструктор, деструктор, сравнение и отображение — может быть применён к объектам и описаниям классов, то описание метакласса Class, которое характеризует описание класса Object, также характеризует себя.

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

При добавлении динамически компонуемых методов, таких как draw(), надо создавать новый метакласс, потому что только его конструктор вставляет адрес метода в описание класса. Описание метакласса всегда использует struct Class и, следовательно, создаётся с помощью вызова

 

PointClass = new(Class, ...

            ctor, PointClass_ctor,

            0);

 

Создав описание метакласса, мы можем создавать описания классов в этом метаклассе и вставить новый метод:

 

Point = new(PointClass, ...

            draw, Point_draw,

            ...

            0);

 

Эти два вызова должны быть выполнены только один раз, до того, как смогут быть созданы любые объекты нового класса. Существует стандартный способ написать все конструкторы метаклассов так, чтобы пары селектор / метод можно было указывать в любом порядке. Другие классы в том же метаклассе могут быть созданы просто отсылкой new() к описанию метакласса.

Селекторы также пишутся стандартным образом. Хорошей идеей является принять решение о порядке вызовов для конструкторов и деструкторов, чтобы всегда помещать вызовы по цепочке суперклассов вместе. Для упрощения кодирования предоставляем селекторам суперклассов те же аргументы, что и селекторам; должен быть указан дополнительный первый параметр как класс, для которого определён метод, вызывающий селектор суперкласса. Селекторы суперклассов тоже пишутся в соответствии со стандартным шаблоном.

Логически последовательный стиль проверок делает реализации более или менее надёжными: селекторы проверяют объект, его класс, а также существование метода; селекторы суперкласса должны дополнительно проверить аргумент нового класса; динамически скомпонованный метод вызывается только через селектор, то есть не надо проверять его объект. Статически скомпонованный метод ничем не отличается от селектора: он должен проверять объект своего аргумента.

Давайте рассмотрим смысл двух основных компонентов объектов и описаний классов и наших соглашений об именах. У каждого класса в конце концов суперклассом выступает Object. Если взять указатель p на объект в произвольном подклассе Object, компонент p->class указывает на описание класса данного объекта. Предположим, что указатель C указывает на то же описание класса и что C является именем класса, опубликованным в файле интерфейса C.h. Тогда объект по адресу в p будет представлен с помощью struct C. Это объясняет, почему в разделе 6.3 Class−>class должен указывать на сам Class: объект, на который указывает Class, представлен в виде struct Class.

Каждое описание класса должно начинаться со struct Class для хранения всего, подобного имени класса или указателя на описание суперкласса. Пусть теперь C указывает на описание класса и пусть C−>super указывает на то же описания класса, что и указатель S, опубликованный в файле интерфейса S.h, то есть S является суперклассом C. В этом случае struct C должна начинаться со struct S. Это объясняет, почему в разделе 6.3 Class−>super должен указывать на Object: мы решили, что struct Class начинается с struct Object.

Единственным исключением из этого правила является тот факт, что Object−>super имеет значение Object, хотя как было указано в разделе 6.3, это было довольно спорное решение.

 

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