Nejčastěji při programování v Delphi nemusíte dynamicky vytvářet komponenty. Pokud komponentu přetáhnete do formuláře, zpracovává Delphi vytvoření komponenty automaticky při vytvoření formuláře. Tento článek se zabývá správným způsobem, jak programově vytvářet součásti za běhu.
Dynamické vytváření komponent
Existují dva způsoby, jak dynamicky vytvářet součásti. Jedním ze způsobů je učinit z formuláře (nebo nějaké jiné komponenty TCom) vlastníka nové komponenty. Toto je běžná praxe při vytváření složených komponent, kde vizuální kontejner vytváří a vlastní dílčí komponenty. Tím zajistíte, že nově vytvořená komponenta bude zničena, když bude zničena vlastnící komponenta.
Chcete-li vytvořit instanci (objekt) třídy, voláte její metodu "Vytvořit". Vytvořit konstruktor je metoda třídy, na rozdíl od prakticky všech ostatních metod, se kterými se setkáte v programování Delphi, což jsou objektové metody.
Například TComponent deklaruje konstruktor Create takto:
konstruktor Create (AOwner: TComponent); virtuální;
Dynamická tvorba s vlastníky
Zde je příklad dynamického stvoření Já je TComponent nebo TComponent potomek (např. instance TForm):
s TTimer. Vytvořit (Self) do
začít
Interval: = 1000;
Enabled: = False;
OnTimer: = MyTimerEventHandler;
konec;
Dynamické stvoření s výslovným voláním zdarma
Druhým způsobem vytvoření komponenty je použití nula jako majitel. Pokud to uděláte, musíte také explicitně uvolnit objekt, který vytvoříte, jakmile jej již nepotřebujete (nebo vytvoříte únik paměti). Zde je příklad použití nil jako vlastníka:
s TTable. Vytvořte (žádné)
Snaž se
DataBaseName: = 'MyAlias';
TableName: = 'MyTable';
Otevřeno;
Upravit;
FieldByName ('Busy'). AsBoolean: = True;
Pošta;
Konečně
Volný, uvolnit;
konec;
Dynamické vytváření a odkazy na objekty
Je možné vylepšit dva předchozí příklady přiřazením výsledku volání Create k proměnné místní metodě nebo náležející do třídy. To je často žádoucí, když se odkazuje na komponent je třeba použít později nebo kdy rozsah je třeba se vyhnout problémům způsobeným bloky „With“. Zde je kód pro vytvoření TTimeru shora, s použitím proměnné pole jako odkazu na instanční objekt TTimeru:
FTimer: = TTimer. Vytvořit (vlastní);
s FTimerem
začít
Interval: = 1000;
Enabled: = False;
OnTimer: = MyInternalTimerEventHandler;
konec;
V tomto příkladu je "FTimer" soukromá proměnná pole formuláře nebo vizuálního kontejneru (nebo cokoli "Self" je). Při přístupu k proměnné FTimer z metod v této třídě je velmi dobré zkontrolovat, zda je odkaz platný před použitím. To se provádí pomocí funkce Delphi's Assigned:
pokud je přiřazeno (FTimer), pak FTimer. Povoleno: = True;
Dynamické vytváření a odkazy na objekty bez vlastníků
Varianta je vytvořit komponentu bez vlastníka, ale zachovat odkaz pro pozdější zničení. Konstrukční kód pro TTimer by vypadal takto:
FTimer: = TTimer. Vytvořit (žádné);
s FTimerem
začít
...
konec;
A kód ničení (pravděpodobně v destruktoru formuláře) by vypadal asi takto:
FTimer. Volný, uvolnit;
FTimer: = žádný;
(*
Nebo použijte proceduru FreeAndNil (FTimer), která uvolní odkaz na objekt a nahradí odkaz nulovým.
*)
Při uvolňování objektů je rozhodující nastavení odkazu na nulu. Volání na Free nejprve zkontroluje, zda je odkaz na objekt nulový nebo ne, a pokud tomu tak není, volá destruktor objektu.
Dynamické vytváření a odkazy na místní objekty bez vlastníků
Zde je kód vytvoření TTable shora, pomocí místní proměnné jako odkazu na instanční objekt TTable:
localTable: = TTable. Vytvořit (žádné);
Snaž se
s localTable do
začít
DataBaseName: = 'MyAlias';
TableName: = 'MyTable';
konec;
...
// Později, pokud chceme explicitně určit rozsah:
localTable. Otevřeno;
localTable. Upravit;
localTable. FieldByName ('Busy'). AsBoolean: = True;
localTable. Pošta;
Konečně
localTable. Volný, uvolnit;
localTable: = nil;
konec;
Ve výše uvedeném příkladu je "localTable" a lokální proměnná deklarováno stejnou metodou obsahující tento kód. Všimněte si, že po uvolnění jakéhokoli objektu je obecně velmi dobré nastavit odkaz na nulu.
Varovné slovo
DŮLEŽITÉ: Nemíchejte volání zdarma s předáním platného vlastníka konstruktorovi. Všechny předchozí techniky budou fungovat a jsou platné, ale následující by mělo nikdy se v kódu neobjeví:
s TTable. Vytvořit (vlastní) udělat
Snaž se
...
Konečně
Volný, uvolnit;
konec;
Příklad kódu výše zavádí zbytečné požadavky na výkon, mírně ovlivňuje paměť a má potenciál zavést těžké hledání chyb. Zjistit proč.
Poznámka: Pokud dynamicky vytvořená komponenta má vlastníka (specifikovaného parametrem AOwner konstruktoru Create), pak je tento vlastník zodpovědný za zničení komponenty. V opačném případě musíte explicitně volat zdarma, pokud již komponentu nepotřebujete.
Článek původně napsal Mark Miller
V Delphi byl vytvořen testovací program, který měl časovat dynamickou tvorbu 1000 komponent s různým počátečním počtem komponent. Testovací program se zobrazí v dolní části této stránky. Graf ukazuje sadu výsledků z testovacího programu, porovnávající čas potřebný k vytvoření součástí jak s vlastníky, tak bez nich. Upozorňujeme, že se jedná pouze o část zásahu. Při zničení součástí lze očekávat podobné zpoždění výkonu. Doba dynamického vytváření součástí s vlastníky je o 1200% až 107960% pomalejší než doba pro vytvoření komponenty bez vlastníků, v závislosti na počtu komponent ve formuláři a součásti vytvořeno.
Testovací program
Varování: Tento testovací program nesleduje a neobsahuje komponenty, které jsou vytvořeny bez vlastníků. Nesledováním a uvolněním těchto součástí doby měřené pro kód dynamické tvorby přesněji odrážejí reálný čas pro dynamické vytvoření komponenty.
Stáhněte si zdrojový kód
Varování!
Pokud chcete dynamicky vytvořit instanci komponenty Delphi a explicitně ji uvolnit někdy později, vždy předejte jako majitel nulovou hodnotu. Pokud tak neučiníte, může to představovat zbytečné riziko a problémy s výkonem a údržbou kódu. Přečtěte si článek „Upozornění na dynamicky se rozvíjející komponenty Delphi“ a získejte více informací ...