Meestal hoeft u bij het programmeren in Delphi niet dynamisch een component te maken. Als u een component op een formulier neerzet, verwerkt Delphi de componentcreatie automatisch wanneer het formulier wordt gemaakt. Dit artikel behandelt de juiste manier om programmatisch componenten te maken tijdens runtime.
Creatie van dynamische componenten
Er zijn twee manieren om componenten dynamisch te maken. Een manier is om een formulier (of een andere TComponent) eigenaar te maken van de nieuwe component. Dit is een gebruikelijke praktijk bij het bouwen van samengestelde componenten waarbij een visuele container de subcomponenten maakt en bezit. Als u dit doet, zorgt u ervoor dat de nieuw gemaakte component wordt vernietigd wanneer de eigen component wordt vernietigd.
Om een instantie (object) van een klasse te maken, noemt u de "Create" -methode. De constructor Create is een klasse methode, in tegenstelling tot vrijwel alle andere methoden die u tegenkomt in Delphi-programmering, dit zijn objectmethoden.
De TComponent verklaart de Create-constructor bijvoorbeeld als volgt:
constructor Maken (AOwner: TComponent); virtueel;
Dynamische creatie met eigenaren
Hier is een voorbeeld van dynamische creatie, waar Zelf is een TComponent of TComponent-afstammeling (bijvoorbeeld een instantie van een TForm):
met TTimer. Maken (zelf) doen
beginnen
Interval: = 1000;
Ingeschakeld: = False;
OnTimer: = MyTimerEventHandler;
einde;
Dynamische creatie met een expliciete gratis oproep
De tweede manier om een component te maken is om te gebruiken nihil als de eigenaar. Merk op dat als u dit doet, u ook het object dat u maakt expliciet moet bevrijden zodra u het niet langer nodig hebt (of u produceert een geheugenlek). Hier is een voorbeeld van het gebruik van nul als de eigenaar:
met TTable. Maken (nihil) doen
proberen
DataBaseName: = 'MyAlias';
TableName: = 'MyTable';
Open;
Bewerk;
FieldByName ('Busy'). AsBoolean: = True;
Post;
Tenslotte
Vrij;
einde;
Dynamische creatie en objectreferenties
Het is mogelijk om de twee voorgaande voorbeelden te verbeteren door het resultaat van de aanroep Create aan een variabele toe te wijzen die lokaal is voor de methode of die tot de klasse behoort. Dit is vaak wenselijk wanneer verwijzingen naar de component moeten later worden gebruikt, of wanneer scoping problemen die mogelijk worden veroorzaakt door "With" -blokken moeten worden vermeden. Hier is de TTimer-aanmaakcode van hierboven, met behulp van een veldvariabele als referentie naar het instantiërde TTimer-object:
FTimer: = TTimer. Maken (zelf);
met FTimer doen
beginnen
Interval: = 1000;
Ingeschakeld: = False;
OnTimer: = MyInternalTimerEventHandler;
einde;
In dit voorbeeld is "FTimer" een variabele van het privéveld met de vorm of visuele container (of wat "Zelf" ook is). Wanneer u de FTimer-variabele opent vanuit methoden in deze klasse, is het een goed idee om te controleren of de referentie geldig is voordat u deze gebruikt. Dit wordt gedaan met behulp van de toegewezen functie van Delphi:
indien toegewezen (FTimer) dan FTimer. Ingeschakeld: = True;
Dynamische creatie en objectreferenties zonder eigenaren
Een variatie hierop is om de component te maken zonder eigenaar, maar de referentie te behouden voor latere vernietiging. De constructiecode voor de TTimer ziet er als volgt uit:
FTimer: = TTimer. Maken (nul);
met FTimer doen
beginnen
...
einde;
En de vernietigingscode (vermoedelijk in de destructor van de vorm) zou er ongeveer zo uitzien:
FTimer. Vrij;
FTimer: = nul;
(*
Of gebruik de FreeAndNil (FTimer) procedure, die een objectreferentie bevrijdt en de referentie door nul vervangt.
*)
Het instellen van de objectreferentie op nul is cruciaal bij het vrijmaken van objecten. De aanroep naar Free controleert eerst of de objectreferentie nul is of niet, en als dit niet het geval is, wordt de destructor van het object Destroy genoemd.
Dynamische creatie en lokale objectreferenties zonder eigenaren
Hier is de TTable-aanmaakcode van hierboven, met behulp van een lokale variabele als verwijzing naar het instantiërende TTable-object:
localTable: = TTable. Maken (nul);
proberen
met localTable doen
beginnen
DataBaseName: = 'MyAlias';
TableName: = 'MyTable';
einde;
...
// Later, als we het bereik expliciet willen specificeren:
localTable. Open;
localTable. Bewerk;
localTable. FieldByName ('Busy'). AsBoolean: = True;
localTable. Post;
Tenslotte
localTable. Vrij;
localTable: = nul;
einde;
In het bovenstaande voorbeeld is "localTable" een lokale variabele aangegeven in dezelfde methode die deze code bevat. Merk op dat na het bevrijden van een object het in het algemeen een goed idee is om de referentie op nul te zetten.
Een waarschuwing
BELANGRIJK: meng een oproep naar Free niet met het doorgeven van een geldige eigenaar aan de constructor. Alle voorgaande technieken werken en zijn geldig, maar het volgende zou moeten kom nooit in uw code voor:
met TTable. Maken (zelf) doen
proberen
...
Tenslotte
Vrij;
einde;
Het bovenstaande codevoorbeeld introduceert onnodige prestaties, beïnvloedt het geheugen enigszins en heeft het potentieel om moeilijk te vinden bugs te introduceren. Erachter te komen waarom.
Opmerking: als een dynamisch gemaakt onderdeel een eigenaar heeft (gespecificeerd door de AOwner-parameter van de constructor Maken), dan is die eigenaar verantwoordelijk voor het vernietigen van het onderdeel. Anders moet u expliciet Gratis bellen als u het onderdeel niet langer nodig hebt.
Artikel oorspronkelijk geschreven door Mark Miller
Een testprogramma is gemaakt in Delphi om de dynamische creatie van 1000 componenten met variërende initiële aantal componenten te timen. Het testprogramma verschijnt onderaan deze pagina. De grafiek toont een set resultaten van het testprogramma, waarbij de tijd wordt vergeleken die nodig is om componenten te maken, zowel met als zonder eigenaars. Merk op dat dit slechts een deel van de hit is. Een vergelijkbare prestatievertraging kan worden verwacht bij het vernietigen van componenten. De tijd om dynamisch componenten te maken met eigenaren is 1200% tot 107960% langzamer dan die om te maken componenten zonder eigenaars, afhankelijk van het aantal componenten op de vorm en de component die is gemaakt.
Het testprogramma
Waarschuwing: dit testprogramma houdt geen componenten bij die gratis zijn gemaakt zonder eigenaren. Door deze componenten niet te volgen en vrij te geven, geven de gemeten tijden voor de dynamische creatiecode een nauwkeuriger beeld van de realtime om een component dynamisch te creëren.
Download broncode
Waarschuwing!
Als u een Delphi-component dynamisch wilt instantiëren en deze ergens later expliciet wilt bevrijden, moet u altijd als nul doorgaan. Als u dit niet doet, kan dit onnodige risico's en prestatie- en codeonderhoudsproblemen veroorzaken. Lees het artikel "Een waarschuwing over Delphi-componenten die dynamisch worden instantieerd" voor meer informatie ...