Jak jsem již psal, Delphi 2007 přináší do jazyka koncepci Class Helper. Jedná se o možnost rozšiřovat existující třídy o metody a property (ale ne pole) bez zásahu do původní třídy. Cílem je mít možnost základní třídy a případné platformové rozšíření implementovat pomocí class helperů.
Raději rovnou příklad. Vytvoříme class helper pro TEdit a pak ho použijeme.
unit uEditHelper;
// class helper pro TEdit
interface
uses
StdCtrls;
type
TEditHelper = class helper for TEdit // deklarace
private
function miGetIntValue: Integer; // metoda pro property
published
function CheckForInt: Boolean; // přidáme metodu na validaci
property IntValue:Integer read miGetIntValue; // a property
end;
implementation
uses
SysUtils;
function TEditHelper.CheckForInt: Boolean;
var
iValue:Integer;
begin
Result := TryStrToInt(Text, iValue);
end;
function TEditHelper.miGetIntValue: Integer;
begin
Result := StrToInt(Text);
end;
end.
Nyní máme tedy class helper a snad tam není nic komplikovaného. Jak ho ale použijeme? Použití class helperů je možné v rámci viditelnosti. Tedy v místě, kde chceme používat naše rozšíření na ně musíme "vidět", tj. musí být v uses.
Mějme klasický formulář s jedním tlačítkem (TButton) a jedním editačním polem (TEdit), do uses dáme náš class helper a dopíšeme obsluhu OnClick tlačítka dle uvedeného kódu:
var
Form1: TForm1;
implementation
uses
uEditHelper;
{$R *.dfm}
procedure TForm1.Button1Click(Sender: TObject);
var
i:Integer;
begin
if not Edit1.CheckForInt then
ShowMessage(Format('Neplatná hodnota [%s]', [Edit1.Text]));
i := Edit1.IntValue;
end;
Pokud by nebyl class helper (uEditHelper) v uses tak by náš kód nešel přeložit. Volání helperu je celkem přímočaré, prostě nad editačním polem zavoláme metodu helperu, případně použijeme property v něm definovanou.
Znovu opakuji, že nelze přidávat žádné pole (tj. žádné proměnné třídy), tj. musíte operovat nad existujícími daty.
Jen pro zajímavost ukáži jak vypadá výsledný kód. Je evidentní, že použití class helperů nemá žádnou režii ohledně volání:
Unit1.pas.32: if not Edit1.CheckForInt then
0045DA97 8B8364030000 mov eax,[ebx+$00000364]
0045DA9D E876FDFFFF call TEditHelper.CheckForInt
0045DAA2 84C0 test al,al
0045DAA4 7533 jnz $0045dad9
Unit1.pas.33: ShowMessage(Format('Neplatná hodnota [%s]', [Edit1.Text]));
0045DAA6 8D45FC lea eax,[ebp-$04]
0045DAA9 50 push eax
0045DAAA 8D55F0 lea edx,[ebp-$10]
0045DAAD 8B8364030000 mov eax,[ebx+$00000364]
0045DAB3 E8A0F4FDFF call TControl.GetText
0045DAB8 8B45F0 mov eax,[ebp-$10]
0045DABB 8945F4 mov [ebp-$0c],eax
0045DABE C645F80B mov byte ptr [ebp-$08],$0b
0045DAC2 8D55F4 lea edx,[ebp-$0c]
0045DAC5 33C9 xor ecx,ecx
0045DAC7 B818DB4500 mov eax,$0045db18
0045DACC E813BAFAFF call Format
0045DAD1 8B45FC mov eax,[ebp-$04]
0045DAD4 E8530DFDFF call ShowMessage
Unit1.pas.34: i := Edit1.IntValue;
0045DAD9 8B8364030000 mov eax,[ebx+$00000364]
0045DADF E88CFDFFFF call TEditHelper.miGetIntValue
Unit1.pas.36: end;
0045DAE4 33C0 xor eax,eax