Pokrywanie i redeklarowanie właściwości


Deklaracja właściwości, która nie ma wyspecyfikowanego typu, nazywana jest pokrywaniem właściwości. Pokrywanie właściwości pozwala na zmianę widoczności lub specyfikatorów właściwości odziedziczonych. Najprostrze pokrycie składa się jedynie ze słowa kluczowego property poprzedzającego identyfikator odziedziczonej właściwości; ta forma jest używana do zmiany widoczności właściwości. Przykładowo, jeśli klasa-przodek deklaruje właściwość jako protected, w klasie potomnej można ją redeklarować w sekcji public, lub published. Właściwość pokryta może zawierać dyrektywy read, write, stored, default i nodefault; którakolwiek dyrektywa pokrywa korespondującą z nią odziedziczoną dyrektywę. Pokrywanie może zamienić odziedziczone specyfikatory dostępu, dodać pominięty specyfikator, lub zwiększyć widoczność właściwości, ale nie może usunąć specyfikatora dostępu lub zmniejszyć widoczność właściwości. Pokrycie może włączyć dyrektywę implements, która dodaje do listy zaimplementowanych interfejsów nowy interfejs bez usuwania odziedziczonych.

Następujące deklaracje ilustrują pokrywanie właściwości:

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;

Pokrycie Size dodaje specyfikator write, co czyni właściwość modyfikowalną. Pokrycie Text i Color zmienia widoczność właściwości z protected na published. Pokrycie właściwości Color specyfikuje również zachowywanie wartości w pliku, o ile będzie inna niż clBlue.

Redeklaracja właściwości, zawierająca identyfikator typu, raczej ukrywa odziedziczoną właściwość niż ją pokrywa. Oznacza to, że kreowana jest nowa właściwość o takiej samej nazwie jak odziedziczona. Deklaracja właściwości, specyfikująca typ, musi być kompletną deklaracją, i dlatego musi zawierać co najmniej jeden specyfikator dostępu.

Czy właściwość jest ukryta czy pokryta klasie potomnej, charakter właściwości jest statyczny. Deklarowany (w czasie kompilacji) typ zmiennej użytej do identyfikacji obiektu, determinuje interpretację identyfikatorów jego właściwości. Stąd, po wykonaniu następującego kodu, odczyt lub przypisanie wartości do MyObject.Value wywołuje metodę Method1 lub Method2, nawet jeśli MyObject przechowuje obiekt typu TDescendant. Ale można rzutować typ MyObject na TDescendant aby uzyskać dostęp do właściwości klas potomnych i ich specyfikatorów dostępu.

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;
    i:integer;
 ...
 MyObject := TDescendant.Create;
 MyObject.Value:=123;   // aktywuje Method2
 i:=MyObject.Value;     // aktywuje Method1
 TDescendant(MyObject).Value:=123; // aktywuje Method4
 i:=TDescendant(MyObject).Value;   // aktywuje Method3