Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Gabdullina_Alina_kursovaya.doc
Скачиваний:
16
Добавлен:
23.08.2019
Размер:
1.54 Mб
Скачать

Свойство-массив как основное свойство объекта

Свойство-массив можно сделать основным свойством объектов данного класса. Для этого в описание свойства добавляется слово default:

type

TDelimitedReader = class

...

property Items[Index: Integer]: string read GetItem; default;

...

end;

Такое объявление свойства Items позволяет рассматривать сам объект класса TDelimitedReader как массив и опускать имя свойства-массива при обращении к нему из программы, например:

var

R: TDelimitedReader;

I: Integer;

...

for I := 0 to R.ItemCount - 1 do

Writeln(R[I]);

...

Следует помнить, что только свойства-массивы могут быть основными свойствами объектов; для обычных свойств это недопустимо.

Методы, обслуживающие несколько свойств

Один и тот же метод может использоваться для получения (установки) значений нескольких свойств одного типа. В этом случае каждому свойству назначается целочисленный индекс, который передается в метод чтения (записи) первым параметром.

В следующем примере уже известный Вам метод GetItem обслуживает три свойства: FirstName, LastName и Phone:

type

TDelimitedReader = class

...

property FirstName: string index 0 read GetItem;

property LastName: string index 1 read GetItem;

property Phone: string index 2 read GetItem;

end;

Обращения к свойствам FirstName, LastName и Phone заменяются компилятором на вызовы одного и того же метода GetItem, но с разными значениями параметра Index:

var

Reader: TDelimitedReader;

...

Writeln(Reader.FirstName); // Эквивалентно: Writeln(Reader.GetItem(0));

Writeln(Reader.LastName); // Эквивалентно: Writeln(Reader.GetItem(1));

Writeln(Reader.Phone); // Эквивалентно: Writeln(Reader.GetItem(2));

...

Обратите внимание, что метод GetItem обслуживает как свойство-массив Items, так и свойства FirstName, LastName и Phone. Удобно, не правда ли!

Перед тем, как перейти к более сложным понятиям ООП, приведем полную реализацию класса TDelimitedReader. Настоятельно рекомендуем Вам внимательно ознакомиться с этой реализацией, поскольку в ней сведено воедино все то, о чем говорилось в предыдущих разделах.

type

TDelimitedReader = class

// Поля

FFile: TextFile;

FItems: array of string;

FActive: Boolean;

FDelimiter: Char;

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

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 ADelimiter: Char = ';');

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;

property Delimiter: Char read FDelimiter;

end;

{ TDelimitedReader }

constructor TDelimitedReader.Create(const FileName: string;

const ADelimiter: Char = ';');

begin

AssignFile(FFile, FileName);

FActive := False;

FDelimiter := ADelimiter;

end;

destructor TDelimitedReader.Destroy;

begin

Active := False;

end;

function TDelimitedReader.GetEndOfFile: Boolean;

begin

Result := Eof(FFile);

end;

function TDelimitedReader.GetItem(Index: Integer): string;

begin

Result := FItems[Index];

end;

function TDelimitedReader.GetItemCount: Integer;

begin

Result := Length(FItems);

end;

function TDelimitedReader.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 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;

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