Свойства
Свойство внешне выглядит как поле класса, однако, при доступе к нему на чтение или запись позволяет выполнять некоторые действия. Свойство описывается в классе следующим образом:
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.
Добавление этой проверки позволяет избежать лишней перерисовки кнопки в случае,
если ее ширина не меняется.