ООП - это очень просто

Выпуск № 8  Списки - продолжаем развивать свою базу данных

Но сначала о печальном. Мне пришло письмо с просьбой поделиться информаций о работе с СОМ - портом в Delphi. В своих архивах я нашел три статьи, но вот обе попытки отослать оказались неудачными. Оба сообщения мне вернулись. Так что прошу автора письма maslen@rambler.ru отозваться или просто скачать небольшой архив: com_port.zip. Лежать там он будет две недели ...

Сохранение базы данных в файл

Мы продолжим развивать объект, представляющий собой, по сути дела, базу данных. Предыдущие выпусков можно найти на сайте по адресу http://www.borlpasc.narod.ru/Boris/ogl.htm. Напомню, что исходный код программы состоит из трех частей: модуль uRec.pas, в котором описана структура хранимой единицы информации, модуль BaseObj.pas содержит описание объекта TBaseObj, реализующий нужные действия по сохранению новых данных и выводу их на экран. Третий файл Test.pas выполняет тестирование объекта. Для этого в нем определена переменная типа указатель на объект TBaseObj, программа размещает объект в динамической памяти, добавляет в него одну запись и выводит все хранимые записи на экран. Все три файла в одном архиве можно скачать по адресу http://www.borlpasc.narod.ru/Boris/BaseObj.zip

Добавить следующую запись в конец базы нет можно без проблем. Для этого достаточно добавить строчку кода в программу text.pas

Add(NewOne('Гыр', 'Бор', 123));
Сегодня добавим объекту новое свойство - возможность сохранить базу данных в файл. Но переписывать файл не BaseObj.pas будем! Но для этого нужно будет добавить новый файл и изменить файл Test.pas.

Итак создаем новый файл с исходным текстом, например, uFileObj.pas. В него поместим такой код:

unit uFileObj;
interface
uses BaseObj;

 TYPE
   PFileDBObj = ^TFileDBobj;
   TFileDBobj = object(TBaseObj)
   end;

implementation
END.
Пока еще мы не добавили объекту никаких новых свойств. Просто я хочу показать, как легко в ООП унаследовать свойства объекта. Но тестирующую программу Test.pas теперь сделаем такой:
program Test;
{Программа, тестриующая модуль BaseObj}
uses uFileObj, uRec, CRT;
var
   BO: PFileDBObj;
BEGIN
  ClrScr;
  Bo:=New(PFileDBObj, Init);
  if BO <> nil then
  with BO^ do
  begin
    Add(NewOne('Surin','Борис',12));
    Add(NewOne('Гыр', 'Бор', 123));
    PrintAll;
    Dispose(BO, Done);
  end;
END.
Мы изменили имя используемого модуля на новый и изменили имя используемого модуля, изменили имя объекта. Пришлось немного изменить и содержимое оператора New. А программа работает по-прежнему!

Пойдем дальше. В объект TFileDBobj добавим метод: procedure SaveToFile(AFileName: String). Ниже приводится код модуля, в котором описано простейшая реализация метода.

unit uFileObj;
interface
uses BaseObj, uRec;

 TYPE
   PFileDBObj = ^TFileDBobj;
   TFileDBobj = object(TBaseObj)
    procedure SaveToFile(AFileName: string);
   end;

implementation

procedure TFileDBobj.SaveToFile;
var
   f: File of TInfo;
   p: POne;
begin
  Assign(f, AFileName);
  {$I-} Rewrite(f); {$I+}
  if IOResult <> 0 then begin
    {Файл не удалось открыть (создать)}
    WriteLn('Скорее всего имя файла содержит недопустимые символы: ',
          AFileName);
    Exit;
  end;
  p:=GetNode;
  while p <> nil do begin
    Write(f, p^.Info);
    p:=p^.Next
  end;
  Close(f);
end;
END.
Краткое описание метода SaveToFile. В нем объявлена файловая переменная f, которая описывает типизированный файл, состоящий из записей TInfo, и переменная p типа POne. А далее все почти просто: начиная с первого узла записываем в файл структуры TInfo с помощью команды Write(f, p^.Info) содержимое записи, и переходим к следующему узлу.

Обращу внимание на то, что появился новый метод GetNode. Его необходимо добавить к "прежнему" объекту TBaseObj:

     TBaseObj = object
     private
        Node: POne;
     public
      constructor Init;
      destructor Done; virtual;
      procedure Add(ANewOne: POne); virtual;
      procedure PrintAll; virtual;
      function GetNode: POne;
     end;
     ....
function TBaseObj.GetNode: POne;
begin
  GetNode:=Node
end;
Поле Node объявлено в разделе PRIVATE и оно недоступно из наследника объекта TFileDBobj, но объявлять поле Node доступным опасно. Пользователь может что-то дописать к программе, изменить значение поля и, в лучшем случае, потеряет возможность обратиться к первым полям базы данных. Выход из, казалось бы, тупиковой ситуации заключается в создании общедоступного (PUBLIC) метода, который только возвращает значение указателя.

Чтение базы данных из файла

Чтобы загрузить данные из файла необходимо в объект TFileDBobj добавить метод LoadFromFile. Код этого метода дается ниже:

procedure TFileDBobj.LoadFromFile(AFileName: String);
var
  f: File of TInfo;
  i: TInfo;
begin
  Assign(f, AFileName);
  {$I-} Reset(f); {$I+}
  if IOResult <> 0 then begin
    WriteLn('Не могу открыть файл с исходными данными ',AFileName);
    Exit;
  end;
  {Считаем идентификационную запись и сверим ее со "стандартном"}
  {$I-} (* Возможны ошибки при чтении информации - вдруг это совсем
           другой файл - не "наш" *)
        Read(f, i);
        if i.Name <> cVersion then begin
         WriteLn('Несоответствие версий баз данных:', i.Name);
         Close(f); Exit;
         {Просто закрываем файл и выходим из процедуры}
        end;
        {Добавляем в дазу данных}
        Add(NewOne(i.Name, i.ForeName, i.Age));
   {Считываем все остальные и добавляем. По-видимому,
    проверять на правильность считывания не стоит - если
    первая запись правильная, то скорее всего и
    остальные тоже}
   while NOT EOF(f) do begin
     Read(f, i);
     Add(NewOne(i.Name, i.ForeName, i.Age));
   end;
  {$I+}
  Close(f);
end;

Добавить его в объект, надеюсь, сумеете сами. Если нет, то скачайте архив с исходным кодом всех описанных программ: http://www.borlpasc.narod.ru/Boris/oop008.zip

Удачи. Пишите, ежели что ...

[ в начало ]

© Борис Сурин

Рассылку поддерживает сайт www.turbopascal.tk

При перепечатке ссылка на сайт обязательна

Hosted by uCoz