Свойство (Property)

В этом разделе мы изучаем определение, синтаксис, стандарты и сериализацию свойств (Property)

Что такое Property

property — синтаксический сахар Pascal. Снаружи он ведёт себя как обычное поле, а под капотом фактически вызывает геттер для чтения / сеттер для записи. Он нужен для инкапсуляции закрытых полей, унификации логики чтения и записи, а также добавления побочных эффектов.

  1. Управляемое свойство чтения-записи: при присваивании или получении значения автоматически запускается дополнительная логика (перерисовка интерфейса, синхронизация компонентов, проверка корректности чисел) ;
  2. Только читаемое свойство: из внешнего кода доступно только для чтения, прямое присваивание запрещено; изменение данных реализовано через внутренние специальные процедуры.
program Demo;
{$ifdef FPC} {$mode objfpc}{$H+}{$J-} {$endif}
{$ifdef MSWINDOWS} {$apptype CONSOLE} {$endif}
uses
  SysUtils;

type
  TWebPage = class
  private
    FURL: string;
    FColorRGB: Integer;
    procedure SetColorRGB(const Value: Integer);
  public
    property URL: string read FURL;
    property ColorRGB: Integer read FColorRGB write SetColorRGB;

    procedure Load(const AnURL: string);
    procedure PrintStatus;
  end;

procedure TWebPage.Load(const AnURL: string);
begin
  FURL := AnURL;
  Writeln('Load page: ', AnURL);
end;

procedure TWebPage.SetColorRGB(const Value: Integer);
begin
  if FColorRGB <> Value then
  begin
    FColorRGB := Value;
    Writeln('Color updated, value = ', Value);
    Writeln('Sync component color to ', Value);
  end;
end;

procedure TWebPage.PrintStatus;
begin
  Writeln('==== Page Info ====');
  Writeln('URL(read-only): ', URL);
  Writeln('ColorRGB(rw): ', ColorRGB);
  Writeln('==================');
  Writeln;
end;

var
  Page: TWebPage;
begin
  Page := TWebPage.Create;
  try
    Page.Load('https://www.foxdevelop.com/');
    Page.ColorRGB := 255;
    Page.PrintStatus;

    Page.ColorRGB := 255;
    Page.PrintStatus;

    Page.ColorRGB := 65535;
    Page.PrintStatus;

    // Page.URL := 'test'; // Ошибка компиляции, URL только для чтения
  finally
    Page.Free;
  end;
  Readln;
end.Code language: HTML, XML (xml)

В классе TWebPage свойство URL доступно только для чтения, для изменения значения используется процедура Load.

Свойство FColorRGB поддерживает чтение, запись и изменение его значения осуществляется через процедуру SetColorRGB.

Процедура PrintStatus является обычной процедурой для вывода внутренних данных объекта TWebPage.

Результат выполнения программы

Load page: https://www.foxdevelop.com/
Color updated, value = 255
Sync component color to 255
==== Page Info ====
URL(read-only): https://www.foxdevelop.com/
ColorRGB(rw): 255
==================

==== Page Info ====
URL(read-only): https://www.foxdevelop.com/
ColorRGB(rw): 255
==================

Color updated, value = 65535
Sync component color to 65535
==== Page Info ====
URL(read-only): https://www.foxdevelop.com/
ColorRGB(rw): 65535
==================Code language: JavaScript (javascript)

2. Правила объявления трёх компонентов свойства

При объявлении свойства обязательно указывается источник чтения, источник записи указывается по желанию:

read источник чтения (выбрать один из двух вариантов)

  • Прямая привязка к закрытому полю (самая быстрая работа, без лишних вызовов функций)
  • Безпараметрическая функция-геттер, возвращающий значение того же типа, что и свойство

write источник записи (опционально; если пропустить — свойство только для чтения): выбрать один из двух вариантов

  • Прямая привязка к закрытому полю
  • Функция-сеттер с одним параметром, тип параметра совпадает с типом свойства

Дополнительные модификаторы исключительно для сериализации: default, stored

Компилятор строго проверяет совпадение типов:

  • Свойство типа Integer: геттер без параметров возвращает Integer / read привязано к закрытому полю Integer
  • Свойство типа String: сеттер принимает параметр const string

Свойства Published и сериализация

1. Что такое сериализация

Запись полных данных объекта в поток (файл/память/JSON) с возможностью последующего восстановления объекта из этого потока;

Файлы форм Lazarus .lfm и Delphi .dfm полностью построены на данном механизме.

  • Основное условие: свойства должны находиться в секции published, чтобы их распознала информация о типах во время выполнения RTTI
  • Вспомогательные модули:
  • LResources: чтение и запись файлов форм lfm
  • FpJsonRtti / CastleComponentSerialize: сериализация объектов в JSON

2. Модификаторы для сериализации

default <константа>: помечает стандартное значение свойства

  • Используется только инструментами сериализации: если после создания объекта значение свойства равно default, оно не сохраняется при сериализации для уменьшения размера файла
  • Автоматической инициализации не происходит: в конструкторе нужно вручную присвоить полю значение из default

stored <булево значение/метод>: управляет сохранением свойства при сериализации

  • stored True: значение по умолчанию, свойство записывается в файл при сериализации
  • stored False: данное свойство никогда не сохраняется
  • stored IsNeedSave: динамическое решение о сохранении через вызов булева метода

Пример сериализации

type
  TWebPage = class
  private
    FColor: TColor;
    function SetColor(const Value: TColor): TColor;
  published
    // default clBlack означает чёрный цвет по умолчанию; конструктор должен прописать FColor := clBlack вручную
    property Color: TColor read FColor write SetColor default clBlack;
    // stored False не сохраняет данные в lfm/json
    property TempCache: string read FTemp write FTemp stored False;
  end;

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *