6.5 Реализация — Object |
Предыдущая Содержание Следующая |
Реализация класса Object прямолинейна: конструктор и деструктор возвращают self, а differ() проверяет, являются ли указатели двух его аргументов равными. Определения этих тривиальных реализаций являются, однако, очень важными: мы используем одно дерево классов и делаем Object конечным суперклассом любого другого класса; если какой-то класс не перезаписывает какой-то метод, например differ(), он наследует его от Object, то есть каждый класс имеет по крайней мере простейшее определение для каждого динамически компонуемого метода уже применимого к Object. Это общий принцип безопасности: всякий раз вводя новый динамически компонуемый метод, мы будем немедленно реализовывать его для этого первого класса. Таким образом мы никогда сможем попасть в ловушку, выбрав совершенно неопределённый метод. Наглядным примером является метод puto() для Object:
static int Object_puto (const void * _self, FILE * fp) { const struct Class * class = classOf(_self);
return fprintf(fp, "%s at %p\n", class -> name, _self); }
Каждый объект указывает на описание класса,и мы сохранили имя класса с описанием. Таким образом, для любого объекта можно по крайней мере показать имя класса и адрес объекта. Первые три строки вывода из тривиальной тестовой программы в разделе 6.4 показывают, что мы не потрудились переписать этот метод для Class или Any. puto() полагается на функцию доступа classOf(), которая выполняет некоторые проверки безопасности и возвращает дескриптор класса объекта:
const void * classOf (const void * _self) { const struct Object * self = _self;
assert(self && self -> class); return self -> class; }
Аналогичным образом можно запросить объект о его размере (* Орфография, вероятно, будет порождать ошибки, но я просто не мог удержаться от каламбура. Изобретение хороших имён методов это искусство) — помните, что в ANSI-C технически объект является простым void *:
size_t sizeOf (const void * _self) { const struct Class * class = classOf(_self);
return class -> size; }
Спорно, следует ли запрашивать объект о размере, или же следует спрашивать его только о классе, а затем явно запрашивать класс о размере. Если мы реализуем sizeOf() для объектов, то не сможем применить его к описанию класса, чтобы получить соответствующий размер объекта — мы получим размер описания самого класса. Тем не менее, практика показывает, что определение sizeOf() для объектов является предпочтительным. super() наоборот является статически скомпонованным методом, который возвращает суперкласс класса, а не объекта.
|
Предыдущая Содержание Следующая |