12.3 Заполнение объектов — geto() |
Предыдущая Содержание Следующая |
geto() является методом Object, который считывает информацию по указателю FILE и заполняет ей объект. geto() применяется к неинициализированному объекту; поэтому его работа весьма схожа с работой конструктора, такого как ctor(). Однако, ctor() берёт информацию для нового объекта из списка аргументов; geto() читает её из входного потока.
Object.d
% Class Object { ... %- : void * geto (_self, FILE * fp); // создание из файла
Пустой тэг определяется предваряющим двоеточием, потому что для инициализированного объекта нет смысла, чтобы метод respondTo возвращал метод geto.
Symbol.dc
% Var geto { struct Var * self = super_geto(Var(), _self, fp);
if (fscanf(fp, "\tvalue %lg\n", & self -> value) != 1) assert(0); return self; }
Var_geto() предоставляет позаботиться об информации инициализации методам суперкласса и просто читает обратно то, что записано Var_puto(). Обычно для fprintf() в методе puto и для fscanf() в методе geto могут быть определены одинаковые форматы . Однако, значения с плавающей точкой показывают незначительную проблему в ANSI-C: fprintf() для преобразования double использует %g, а fscanf() для обратного преобразования требует %lg . Строки обычно должны размещаться в динамической памяти:
% Symbol geto { struct Symbol * self = super_geto(Symbol(), _self, fp); char buf [BUFSIZ];
if (fscanf(fp, "\tname %s\n\tlex %d\n", buf, & self -> lex) != 2) assert(0); self -> name = malloc(strlen(buf) + 1); assert(self -> name); strcpy((char *) self -> name, buf); return self; }
Обычно geto() читает в точности то, что записал соответствующий puto(), и точно так же, как конструкторы, оба метода вызывают методы своих суперклассов, восходящих обратно к Object. Однако, есть одно очень важное отличие: мы видели, что Object_puto() пишет имя класса, сопровождаемое адресом:
Var at 0x50ecb18 Object name x Symbol lex 118 value 1 Var
Object_geto() является первым методом, который заполняет объект Var при чтении входных данных. Имя класса Var, записанное puto(), должно быть прочитано и использовано для выделения памяти объекту Var до того, как для заполнения объекта будет вызван метод geto(), то есть Object_geto() начинает чтение сразу после имени класса:
% Object geto { void * dummy; %casts if (fscanf(fp, " at %p\n", & dummy) != 1) assert(0); return self; }
Это единственное место, где методы geto и puto не соответствуют друг другу. Переменная dummy необходима: можно было бы избежать её использования с помощью элемента формата %*p, но тогда нельзя было бы обнаружить, действительно ли адрес был частью входных данных.
|
Предыдущая Содержание Следующая |