Oprettelse af Delphi-komponenter dynamisk (ved kørsel)

Oftest, når du programmerer i Delphi, behøver du ikke dynamisk at oprette en komponent. Hvis du slipper en komponent på en formular, håndterer Delphi komponentoprettelsen automatisk, når formularen oprettes. Denne artikel dækker den rigtige måde at programmatisk oprette komponenter på runtime.

Oprettelse af dynamisk komponent

Der er to måder at dynamisk oprette komponenter på. En måde er at oprette en formular (eller en anden TComponent) som ejer af den nye komponent. Dette er en almindelig praksis, når man bygger sammensatte komponenter, hvor en visuel beholder opretter og ejer underkomponenterne. Dette vil sikre, at den nyoprettede komponent ødelægges, når den ejer komponent ødelægges.

For at oprette en forekomst (objekt) af en klasse, kalder du dens "Opret" -metode. Create-konstruktøren er en klassemetode, i modsætning til stort set alle andre metoder, du vil støde på i Delphi-programmering, som er objektmetoder.

For eksempel erklærer TComponenten Opret konstruktøren som følger:

konstruktør Opret (AOwner: TComponent); virtuel;

instagram viewer

Dynamisk oprettelse med ejere
Her er et eksempel på dynamisk skabelse, hvor Selv er en TComponent- eller TComponent-efterkommer (f.eks. en forekomst af en TForm):

med TTimer. Opret (Selv) gør
begynde
Interval: = 1000;
Aktiveret: = Falsk;
OnTimer: = MyTimerEventHandler;
ende;

Dynamisk oprettelse med et eksplicit opkald til gratis
Den anden måde at oprette en komponent på er at bruge nul som ejer. Bemærk, at hvis du gør dette, skal du også eksplicit frigøre det objekt, du opretter, så snart du ikke længere har brug for det (eller du vil producere en hukommelsestab). Her er et eksempel på at bruge nil som ejer:

med TTable. Opret (nul) gør
prøve
DataBaseName: = 'MyAlias';
Tabelnavn: = 'MyTable';
Åben;
Redigere;
FieldByName ('Busy'). AsBoolean: = Sandt;
Stolpe;
endelig
Gratis;
ende;

Dynamisk oprettelse og objektreferencer
Det er muligt at forbedre de to foregående eksempler ved at tildele resultatet af Opret opkald til en variabel lokal til metoden eller tilhørende klassen. Dette er ofte ønskeligt, når der henvises til komponent skal bruges senere, eller når områdeafgrænsning problemer, der potentielt er forårsaget af "Med" -blokke, skal undgås. Her er TTimer-oprettelseskoden ovenfra ved hjælp af en feltvariabel som reference til det instantierede TTimer-objekt:

FTimer: = TTimer. Opret (Selv);
med FTimer gør
begynde
Interval: = 1000;
Aktiveret: = Falsk;
OnTimer: = MyInternalTimerEventHandler;
ende;

I dette eksempel er "FTimer" en privat feltvariabel i form eller visuel beholder (eller hvad "Self" er). Når du får adgang til FTimer-variablen fra metoder i denne klasse, er det en meget god ide at kontrollere, om referencen er gyldig, før du bruger den. Dette gøres ved hjælp af Delphis Assigned funktion:

hvis tilordnet (FTimer) så FTimer. Aktiveret: = Sandt;

Dynamisk oprettelse og objektreferencer uden ejere
En variation på dette er at oprette komponenten uden ejer, men opretholde referencen til senere ødelæggelse. Konstruktionskoden til TTimer ser sådan ud:

FTimer: = TTimer. Opret (nul);
med FTimer gør
begynde
...
ende;

Og ødelæggelseskoden (formodentlig i formens destruktør) ville se sådan ud:

FTimer. Gratis;
FTimer: = nul;
(*
Eller brug FreeAndNil (FTimer) -proceduren, der frigiver en objektreference og erstatter referencen med nul.
*)

Indstilling af objektreferencen til nul er kritisk, når man frigiver objekter. Opkaldet til Free kontrollerer først for at se, om objektreferencen er nul eller ej, og hvis den ikke er det, kalder den objektets destruktor Destroy.

Dynamisk oprettelse og lokale objektreferencer uden ejere

Her er TTable-oprettelseskoden ovenfra ved hjælp af en lokal variabel som reference til det instantierede TTable-objekt:

localTable: = TTable. Opret (nul);
prøve
med localTable do
begynde
DataBaseName: = 'MyAlias';
Tabelnavn: = 'MyTable';
ende;
...
// Senere, hvis vi eksplicit vil specificere rækkevidde:
localTable. Åben;
localTable. Redigere;
localTable. FieldByName ('Busy'). AsBoolean: = Sandt;
localTable. Stolpe;
endelig
localTable. Gratis;
localTable: = nul;
ende;

I eksemplet ovenfor er "localTable" en lokal variabel deklareret på samme metode, der indeholder denne kode. Bemærk, at det generelt efter en frigivelse af et objekt er en meget god ide at indstille referencen til nul.

Et advarselsord

VIGTIGT: Bland ikke et opkald til Gratis med at videregive en gyldig ejer til konstruktøren. Alle de tidligere teknikker fungerer og er gyldige, men det følgende bør forekommer aldrig i din kode:

med TTable. Opret (selv) gør
prøve
...
endelig
Gratis;
ende;

Kodeksemplet ovenfor introducerer unødvendige præstationshits, påvirker hukommelsen lidt og har potentialet til at introducere svære at finde fejl. Find ud af hvorfor.

Bemærk: Hvis en dynamisk oprettet komponent har en ejer (specificeret af AOwner-parameteren i Opret konstruktøren), er ejeren ansvarlig for at ødelægge komponenten. Ellers skal du udtrykkeligt ringe gratis, når du ikke længere har brug for komponenten.

Artikel oprindeligt skrevet af Mark Miller

Et testprogram blev oprettet i Delphi for at tidsstyrke den dynamiske oprettelse af 1000 komponenter med forskellige oprindelige komponenttællinger. Testprogrammet vises nederst på denne side. Diagrammet viser et sæt resultater fra testprogrammet, der sammenligner den tid, det tager at oprette komponenter både med ejere og uden. Bemærk, at dette kun er en del af hitet. En lignende ydelsesforsinkelse kan forventes, når komponenter ødelægges. Tiden til dynamisk at oprette komponenter med ejere er 1200% til 107960% langsommere end det at oprette komponenter uden ejere, afhængigt af antallet af komponenter på formularen og komponenten er oprettet.

Testprogrammet

Advarsel: Dette testprogram sporer ikke og frigører komponenter, der oprettes uden ejere. Ved ikke at spore og frigøre disse komponenter afspejler tider målt for den dynamiske oprettelseskode mere nøjagtigt realtiden for dynamisk at oprette en komponent.

Download kildekode

Advarsel!

Hvis du ønsker at dynamisere en Delphi-komponent dynamisk og eksplicit frigøre den engang senere, skal du altid overføre nil som ejer. Hvis du ikke gør det, kan det medføre unødvendig risiko samt ydelses- og kodevedligeholdelsesproblemer. Læs artiklen "En advarsel om dynamisk instantiering af Delphi-komponenter" for at lære mere ...

instagram story viewer