6.6.7 Переопределение свойств

На верх  Назад  Вперёд

Свойства могут быть перекрыты в потомках класса, так же, как и методы. Разница заключается в том, что для свойства, всегда можно сделать overriding (основным): свойства не нужно маркировать как «виртуальное», т.е. они всегда могут быть перекрыты, (в этом смысле, свойства всегда виртуальные). Тип переопределенного свойства не должен быть таким же, как тип свойства родительского класса.

Так как свойство может быть перекрыто, ключевое слово inherited (наследовать) тоже может быть использовано для обозначения родительского свойства. Например, рассмотрим следующий код:

type

  TAncestor = class

    private

      FP1 : Integer;

    public

      property P: integer Read FP1 write FP1;

  end;

 

  TClassA = class(TAncestor)

    private

      procedure SetP(const AValue: char);

      function getP : Char;

    public

      constructor Create;

      property P: char Read GetP write SetP;

  end;

 

procedure TClassA.SetP(const AValue: char);

begin

  Inherited P:=Ord(AValue);

end;

 

procedure TClassA.GetP : char;

begin

  Result:=Char((Inherited P) and $FF);

end;

Класс TClassA переопределяет свойство P как свойство символ вместо целого свойства, но использует свойство родителя P для хранения значения.

Необходимо соблюдать осторожность при использовании виртуальных get/set процедур для свойств: при наследовании свойств применяются теже правила что и при наследовании методов. Рассмотрим следующий пример:

type

  TAncestor = class

    private

      procedure SetP1(const AValue: integer); virtual;

    public

      property P: integer write SetP1;

  end;

 

  TClassA = class(TAncestor)

    private

      procedure SetP1(const AValue: integer); override;

      procedure SetP2(const AValue: char);

    public

      constructor Create;

      property P: char write SetP2;

  end;

 

constructor TClassA.Create;

begin

  inherited P:=3;

end;

В этом случае при установке наследованного свойства P, будет вызываться метод TClassA.SetP1 а не родительский SetP1.

Если при реализация класса, должен быть вызван родительский SetP1, то это должно быть явно указано (обращением не к свойству, к самой функции):

constructor TClassA.Create;

begin

  inherited SetP1(3);

end;