Выпуск № 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
При перепечатке ссылка на сайт обязательна