Свойства (properties), как и поля, являются атрибутами объекта. Поле это хранилище данных, свойство же обеспечивает доступ к этому хранилищу через Read / Write.
Синтаксис свойства следующий
property propertyName[indexes]: type index integerConstant specifiers;
propertyName – валидное название
indexes – это последовательность деклараций, объявленных через точку с запятой, опционально
type тип должен быть предопределен
index – integer константа, опционально
specifiers – это ключевые слова, такие как read, write, stored, default (or nodefault), implements. Также, по крайней мере одно из ключевых слов read / write должно быть объявлено.
Свойства не всегда обязательно существуют в памяти, и поэтому их нельзя передавать как var параметры или через @. Они могут иметь только ключевое слово read, которое добывает значение из базы данных или генерирует случайное значение.
Пример объявления свойства
property Color: TColor read GetColor write SetColor;
При этом метод GetColor должен быть объявлен как
function GetColor: TColor;
А SetColor может быть объявлен одним из следующих способов
procedure SetColor(Value: TColor);
procedure SetColor(const Value: TColor);
Ещё один пример
type
THeading = 0..359;
TCompass = class(TControl)
private
FHeading: THeading;
procedure SetHeading(Value: THeading);
published
property Heading: THeading read FHeading write SetHeading;
...
end;
И вот как мы можем использовать свойства
if Compass.Heading = 180 then GoingSouth;
Compass.Heading := 135;
или
if Compass.FHeading = 180 then GoingSouth;
Compass.SetHeading(135);
Обновление значения могло бы быть таким
procedure TCompass.SetHeading(Value: THeading);
begin
if FHeading <> Value then
begin
FHeading := Value;
Repaint; // update user interface to reflect new value
end;
end;
Индексные свойства
Это могут быть элементы списка, дочерние контролы контрола, пиксели битмапа.
Объявление их следующее
property Objects[Index: Integer]: TObject read GetObject write SetObject;
property Pixels[X, Y: Integer]: TColor read GetPixel write SetPixel;
property Values[const Name: string]: string read GetValue write SetValue;
Get Set методы могли бы быть такими
function GetObject(Index: Integer): TObject;
function GetPixel(X, Y: Integer): TColor;
function GetValue(const Name: string): string;
procedure SetObject(Index: Integer; Value: TObject);
procedure SetPixel(X, Y: Integer; Value: TColor);
procedure SetValue(const Name, Value: string);
И тогда, мы могли бы обращаться так
if Collection.Objects[0] = nil then Exit;
Canvas.Pixels[10, 20] := clRed;
Params.Values['PATH'] := 'C:\BIN';
Или так
if Collection.GetObject(0) = nil then Exit;
Canvas.SetPixel(10, 20, clRed);
Params.SetValue('PATH', 'C:\BIN');
Директива default
Мы можем написать так
type
TStringArray = class
public
property Strings[Index: Integer]: string ...; default;
...
end;
И тогда обращаться так
StringArray[i]
вместо
StringArray.Strings[i]
Ключевое слово index
Мы также можем написать так
type
TRectangle = class
private
FCoordinates: array[0..3] of Longint;
function GetCoordinate(Index: Integer): Longint;
procedure SetCoordinate(Index: Integer; Value: Longint);
public
property Left: Longint index 0 read GetCoordinate
write SetCoordinate;
property Top: Longint index 1 read GetCoordinate
write SetCoordinate;
property Right: Longint index 2 read GetCoordinate
write SetCoordinate;
property Bottom: Longint index 3 read GetCoordinate
write SetCoordinate;
property Coordinates[Index: Integer]: Longint
read GetCoordinate
write SetCoordinate;
...
end;
И тогда, такой синтаксис
Rectangle.Right := Rectangle.Left + 100;
Соответствовал бы
Rectangle.SetCoordinate(2, Rectangle.GetCoordinate(0) + 100);
Storage
Ключевые слова stored, default, and nodefault не будут влиять на поведение программы, но влияют на то, будут ли published свойства сохранены в файлах форм.
Пример использования
property Name: TComponentName read FName write SetName stored False;
ключевое слово default может быть также использовано следующим образом
property Tag: Longint read FTag write FTag default 0;
Наследование свойств
Рассмотрим следующий пример
type
TAncestor = class
...
protected
property Size: Integer read FSize;
property Text: string read GetText write SetText;
property Color: TColor read FColor write SetColor stored False;
...
end;
type
TDerived = class(TAncestor)
...
protected
property Size write SetSize;
published
property Text;
property Color stored True default clBlue;
...
end;
В потомках, мы можем переопределять видимость свойств. Из protected до public / published. Также, в потомке, мы добавили SetSize для Size и удалили read.
Аналогично, мы можем переопределить методы Read / Write
type
TAncestor = class
...
property Value: Integer read Method1 write Method2;
end;
TDescendant = class(TAncestor)
...
property Value: Integer read Method3 write Method4;
end;
var MyObject: TAncestor;
...
MyObject := TDescendant.Create;
Классовые свойства
Определяются следующим образом
type
TMyClass = class
strict private
class var // Note fields must be declared as class fields
FRed: Integer;
FGreen: Integer;
FBlue: Integer;
public // ends the class var block
class property Red: Integer read FRed write FRed;
class property Green: Integer read FGreen write FGreen;
class property Blue: Integer read FBlue write FBlue;
end;
А используются так
TMyClass.Red := 0;
TMyClass.Blue := 0;
TMyClass.Green := 0;