První dva háčky co ukáži slouží k přístupu k private a protected částem cizí třídy umístěné v jiné jednotce. Druhý háček je celkem častý a proto s ním začneme.
Protected pole
Pokud má třída definované pole v sekci protected, neměla by jiná třída, která od ní není odvozená mít k těmto polím přístup. Pro usnadnění programování ale Delphi umožňuje třídě, která je definována ve stejné jednotce přistupovat k protected (a private) polím jiné třídy. Této vlastnosti často využívají tvůrci komponent a někdy zapomenou, že by něco mohli i publikovat.
Samozřejmě ideálním řešením je odvodit vlastní třídu, ale někdy to prostě nejde nebo to není výhodné. Řešením je použití háčku.
V jednotce, kde máme touhu dělat nepravosti (tj. přistupovat na cizí pole) definujeme třídu, která je následníkem inkriminované třídy, ale nemá implementaci. Tj. pro případ, kdy chceme přistupovat k protected polí TButton definujeme
type
TOpenButton = class(TButton);
Nyní můžeme náš inkriminované tlačítko prostě přetypovat a jednoduše přistoupit kam potřebujeme. Následuje nic moc příklad:
TOpenButton(btnTest).SetButtonStyle(true);
Samozřejmě, pokud je místo protected použito strict protected z novějších Delphi tak máte útrum. Což platí i pro strict private.
Private pole
Zatímco předchozí háček je celkem bezpečný a široce používán, druhý se používá až když opravdu jde do tuhého, jelikož je citlivý na změny v základní třídě.
Háček využívá chování kompilátoru. Pro jeho použití musíme znát pořadí polí v sekci private třídy. Pokud tedy nemáme zdrojový kód tak smolík pacholík.
Deklarujeme stínovou třídu, která má i sekci private (proto ten požadavek na zdroják), ale pozor: pořadí jednotlivých polí a jejich typ musí být stejný. Pokud to máme, tak jednoduše už jen cizí třídu přetypujeme na naši stínovou kopii a je to. Tím využijeme dříve popsané chování kdy v rámci jednotky můžeme přistupovat na pole cizí třídy (pokud se tedy nejedná o strict private).
Háček je to pracný a citlivý na změny, proto pozor při jeho používání. Jen pro úplnost připomenu, že pro rozšiřování stávajících tříd lze použít od Delphi 2007 i Class Helper.
Takže malý příklad, kde budou použity oba háčky. Hackujeme TStringList.
program Project2;
{$APPTYPE CONSOLE}
uses
SysUtils, Classes;
type
// demonstrace pristupu k private
TShadowStringLists = class(TStrings)
private
FList: PStringItemList;
FCount: Integer;
FCapacity: Integer;
FSorted: Boolean;
FDuplicates: TDuplicates;
FOnChange: TNotifyEvent;
FOnChanging: TNotifyEvent;
end;
// demonstrace pristupu k protected
TOpenStringList = class(TStringList);
var
sl: TStringList;
begin
sl := TStringList.Create;
try
sl.Add('Prvni');
sl.Add('Druhy');
// pristup k private polozce TStringList.FCount
writeln(TShadowStringLists(sl).FCount);
// pristup k protected metode function TStringList.Get(Index: Integer)
writeln(TOpenStringList(sl).Get(0));
finally
FreeAndNil(sl);
end;
{ Vysledek běhu programu je:
2
Prvni
}
end.
Na řádku 8 - 13 je kopie privátních polí TStringList z Classes.pas, TOpenStringList použijeme pro přístup k protected polím (šlo by samozřejmě použít i tu první třídu, ale nechtěl jsem to motat dohromady). Výsledný kód je pak celkem přímočarý (přidáme dva řetezce a přes háčky vypíšeme počet a první položku).
Příště budou další (nečestné a nesportovní) háčky.