Свойства
Свойство внешне выглядит как поле класса, однако, при доступе к нему на чтение или запись позволяет выполнять некоторые действия. Свойство описывается в классе следующим образом:
property Prop:
тип
readимя функции чтения
writeимя процедуры записи
;
Как правило, каждое свойство связано с некоторым полем класса и возвращает значение этого поля с помощью функции чтения, а меняет - с помощью процедуры записи. Функция чтения и процедура записи должны быть методами этого класса и иметь следующий вид:
function getProp:
тип
; procedure setProp(v:тип
);
Обычно функция чтения и процедура записи описываются в приватной секции класса. Они могут быть виртуальными, в этом случае их уместно описывать в защищенной секции класса.
Вместо
имени функции чтения
и
имени процедуры записи
может фигурировать имя поля, с которым данное свойство связано. Любая из секций read
или write
может быть опущена, в этом
случае мы получаем свойство с доступом только на запись или только на чтение.
Например:
type
Person = class
private
nm: string;
ag: integer;
procedure setAge(a: integer);
begin
if a>=0 then
ag := a
else raise new Exception('Возраст не может быть отрицательным');
end;
function getId: string;
begin
Result := nm + ag.ToString;
end;
public
...
property Age: integer read аg write setAge;
property Name: string read nm;
property Id: string read getId;
end;
var p: Person;
p := new Person('Иванов',20);
p.Age := -3; // генерируется исключение
var i: integer := p.Age;
writeln(p.Id);
Всякий раз, когда мы присваиваем свойству Age
новое значение,
вызывается процедура setAge
с
соответствующим параметром. Всякий раз, когда мы считываем значение свойства
Age
, происходит обращение к полю ag
.
Поле nm
доступно только на
чтение. Наконец, свойство Id
осуществляет
доступ на чтение к информации, находящейся в двух полях.
Обычно для доступа к полю на чтение в секции
read
свойства указывается именно поле,
так как обычно при чтении поля никаких дополнительных действий производить не
требуется.
Свойства не могут передаваться по ссылке в процедуры и функции. Например, следующий код ошибочен:
Inc(p.Age); // ошибка!
Если требуется обработать значение свойства, передав его по ссылке, то надо воспользоваться вспомогательной переменной:
a := p.Age;
Inc(a);
p.Age := a;
Однако, свойства соответствующих типов можно использовать в левой части
операций присваивания += -= *= /=
:
p.Age += 1;
Свойства очень удобны при работе с визуальными объектами,
поскольку позволяют автоматически перерисовывать объект, если изменить
какие-либо его визуальные характеристики. Например, если создана
кнопка b1
типа
Button
,
то для визуального изменения ее ширины достаточно присвоить значение ее свойству
Width
:
b1.Width := 100;
Процедура для записи этого свойства в приватное поле fwidth
будет выглядеть примерно так:
procedure SetWidth(w: integer);
код перерисовки кнопки
begin
if (w>0) and (w<>fwidth) then
begin
fwidth := w;
end
end;
Следует обратить внимание на вторую часть условия в операторе
if
: w<>fwidth
.
Добавление этой проверки позволяет избежать лишней перерисовки кнопки в случае,
если ее ширина не меняется.