Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
delphi.pdf
Скачиваний:
191
Добавлен:
24.02.2016
Размер:
6.84 Mб
Скачать

Result := not EndOfFile;

// Если не достигнут конец файла

if Result then

begin

// Чтение очередной строки из файла

Readln(FFile, S);

N := ParseLine(S);

// Разбор считанной строки

if N <> ItemCount then

// Отсечение массива (если необходимо)

SetLength(FItems, N);

end;

 

end;

 

function TDelimitedReader.ParseLine(const Line: string): Integer;

var

 

S: string;

 

P: Integer;

 

begin

 

S := Line;

 

Result := 0;

 

repeat

// Поиск разделителя

P := Pos(Delimiter, S);

if P = 0 then

// Если разделитель не найден, то

считается, что

// разделитель находится за последним

P := Length(S) + 1;

символом

 

PutItem(Result, Copy(S, 1, P - 1)); // Установка элемента

Delete(S, 1, P);

// Удаление элемента из строки

Result := Result + 1;

// Переход к следующему элементу

until S = '';

// Пока в строке есть символы

end;

 

procedure TDelimitedReader.PutItem(Index: Integer; const Item: string);

begin

// Если индекс выходит за границы

if Index > High(FItems) then

массива,

 

SetLength(FItems, Index + 1); // то увеличение размера массива

FItems[Index] := Item;

// Установка соответствующего элемента

end;

 

procedure TDelimitedReader.SetActive(const AActive: Boolean); begin

if Active <> AActive then // Если состояние изменяется

begin

 

if AActive then

// Открытие файла

Reset(FFile)

else

// Закрытие файла

CloseFile(FFile);

FActive := AActive;

// Сохранение состояния в поле

end;

 

end;

 

3.7. Наследование

3.7.1. Понятие наследования

172

Классы инкапсулируют (т.е. включают в себя) поля, методы и свойства; это их первая черта. Следующая не менее важная черта классов — способность наследовать поля, методы и свойства других классов. Чтобы пояснить сущность наследования обратимся к примеру с читателем текстовых файлов в формате "delimited text".

Класс TDelimitedReader описывает объекты для чтения из текстового файла элементов, разделенных некоторым символом. Он не пригоден для чтения элементов, хранящихся в другом формате, например в формате с фиксированным количеством символов для каждого элемента. Для этого необходим другой класс:

type

TFixedReader = class private

// Поля

FFile: TextFile;

FItems: array of string; FActive: Boolean;

FItemWidths: array of Integer;

// Методы чтения и записи свойств

procedure SetActive(const AActive: Boolean); function GetItemCount: Integer;

function GetEndOfFile: Boolean;

function GetItem(Index: Integer): string; // Методы

procedure PutItem(Index: Integer; const Item: string); function ParseLine(const Line: string): Integer; function NextLine: Boolean;

// Конструкторы и деструкторы

constructor Create(const FileName: string; const AItemWidths: array of Integer);

destructor Destroy; override; // Свойства

property Active: Boolean read FActive write SetActive; property Items[Index: Integer]: string read GetItem; default; property ItemCount: Integer read GetItemCount;

property EndOfFile: Boolean read GetEndOfFile; end;

{ TFixedReader }

constructor TFixedReader.Create(const FileName: string; const AItemWidths: array of Integer);

var

I: Integer; begin

AssignFile(FFile, FileName); FActive := False;

// Копирование AItemWidths в FItemWidths SetLength(FItemWidths, Length(AItemWidths));

173

for I := 0 to High(AItemWidths) do FItemWidths[I] := AItemWidths[I];

end;

destructor TFixedReader.Destroy; begin

Active := False; end;

function TFixedReader.GetEndOfFile: Boolean; begin

Result := Eof(FFile); end;

function TFixedReader.GetItem(Index: Integer): string; begin

Result := FItems[Index]; end;

function TFixedReader.GetItemCount: Integer; begin

Result := Length(FItems); end;

function TFixedReader.NextLine: Boolean; var

S: string;

 

N: Integer;

 

begin

 

Result := not EndOfFile;

// Если не достигнут конец файла

if Result then

begin

// Чтение очередной строки из файла

Readln(FFile, S);

N := ParseLine(S);

// Разбор считанной строки

if N <> ItemCount then

// Отсечение массива (если необходимо)

SetLength(FItems, N);

end;

 

end;

 

function TFixedReader.ParseLine(const Line: string): Integer; var

I, P: Integer; begin

P := 1;

for I := 0 to High(FItemWidths) do begin

PutItem(I, Copy(Line, P, FItemWidths[I]));

// Установка элемента

P :=

P + FItemWidths[I];

// Переход к следующему

элементу

 

 

end;

:= Length(FItemWidths); // Количество

элементов постоянно

Result

end;

 

 

procedure TFixedReader.PutItem(Index: Integer; const Item: string);

174

begin

// Если индекс выходит за границы

if Index > High(FItems) then

массива,

 

SetLength(FItems, Index + 1); // то увеличение размера массива

FItems[Index] := Item;

// Установка соответствующего элемента

end;

 

procedure TFixedReader.SetActive(const AActive: Boolean); begin

if Active <> AActive then // Если состояние изменяется

begin

 

if AActive then

// Открытие файла

Reset(FFile)

else

// Закрытие файла

CloseFile(FFile);

FActive := AActive;

// Сохранение состояния в поле

end;

 

end;

 

Поля, свойства и методы класса TFixedReader практически полностью аналогичны тем, что определены в классе TDelimitedReader. Отличие состоит в отсутствии свойства Delimiter, наличии поля FItemWidths (для хранения размеров элементов), другой реализации метода ParseLine и немного отличающемся конструкторе. Если в будущем появится класс для чтения элементов из файла еще одного формата (например, зашифрованного текста), то придется снова определять общие для всех классов поля, методы и свойства. Чтобы избавиться от дублирования общих атрибутов (полей, свойств и методов) при определении новых классов, воспользуемся механизмом наследования. Прежде всего, выделим в отдельный класс TTextReader общие атрибуты всех классов, предназначенных для чтения элементов из текстовых файлов. Реализация методов TTextReader, кроме метода ParseLine, полностью идентична реализации TDelimitedReader, приведенной в предыдущем разделе.

type

TTextReader = class private

// Поля

FFile: TextFile;

FItems: array of string; FActive: Boolean;

//Методы получения и установки значений свойств procedure SetActive(const AActive: Boolean); function GetItemCount: Integer;

function GetItem(Index: Integer): string; function GetEndOfFile: Boolean;

//Методы

procedure PutItem(Index: Integer; const Item: string); function ParseLine(const Line: string): Integer;

175

function NextLine: Boolean; // Конструкторы и деструкторы

constructor Create(const FileName: string); destructor Destroy; override;

// Свойства

property Active: Boolean read FActive write SetActive; property Items[Index: Integer]: string read GetItem; default; property ItemCount: Integer read GetItemCount;

property EndOfFile: Boolean read GetEndOfFile; end;

...

constructor TTextReader.Create(const FileName: string); begin

AssignFile(FFile, FileName); FActive := False;

end;

function TTextReader.ParseLine(const Line: string): Integer; begin

//Функция просто возвращает 0, поскольку не известно,

//в каком именно формате хранятся элементы

Result := 0; end;

...

При реализации класса TTextReader ничего не известно о том, как хранятся элементы в считываемых строках, поэтому метод ParseLine ничего не делает. Очевидно, что создавать объекты класса TTextReader не имеет смысла. Для чего тогда нужен класс TTextReader? Ответ: чтобы на его основе определить

(породить) два других класса — TDelimitedReader и TFixedReader,

предназначенных для чтения данных в конкретных форматах:

type

TDelimitedReader = class(TTextReader) FDelimiter: Char;

function ParseLine(const Line: string): Integer; override; constructor Create(const FileName: string; const ADelimiter: Char =

';');

property Delimiter: Char read FDelimiter; end;

TFixedReader = class(TTextReader) FItemWidths: array of Integer;

function ParseLine(const Line: string): Integer; override; constructor Create(const FileName: string;

const AItemWidths: array of Integer);

end;

...

Классы TDelimitedReader и TFixedReader определены как наследники

TTextReader (об этом говорит имя в скобках после слова class). Они

176

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]