12.3 Заполнение объектов — geto()

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

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, но тогда нельзя было бы обнаружить, действительно ли адрес был частью входных данных.

 

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