Image
17.6.2016 0 Comments

Stretnutie s Pascalom II. /6. časť

Späť na úvod >> Späť na programovanie >> Späť na seriál

Ak si dobre pozrieme naše posledné zdrojové texty, zistíme, že metóda Draw má rôzne implementácie v závislosti od objektu, z ktorého je volaná. Môžeme povedať, že vďaka virtualite je akási "viactvará". Tomuto javu hovoríme polymorfizmus. A ako vieme, je to jeden zo základných princípov OOP, s ktorým sa budeme odteraz často stretávať.
            Objekty, či lepšie povedané ich inštancie, o ktorých sme si doteraz hovorili, boli statické:

var
    Bod : Point;
    Kruznica : Circle;
           
Ak pracujeme s objektmi, ktorých počet sa pri behu programu mení, a použijeme na ich reprezentáciu statickú štruktúru, napr. pole, musíme už pri písaní programu odhadovať maximálny počet týchto objektov a podľa toho pamäť alokovať. Tento spôsob sa vo väčšine príkladov stáva nepraktickým, ba dokonca pri zlom odhade počtu objektov môže program kolabovať. Často je výhodnejšie použiť dynamicky alokované objekty, ktorých pamäť uvoľníme, lenčo ich už nebudeme potrebovať. Takéto objekty sú prístupné prostredníctvom ukazovateľov, tak ako to poznáme pri premenných ostatných typov. Navyše je Turbo Pascal od verzie 5.5 vybavený rozšírením, ktoré umožňuje jednoduchšiu a efektívnejšiu alokáciu a uvoľňovanie dynamických objektov v pamäti.
Ak máme

 

type
    CirclePtr = ^Circle;
 
var
   uKruznica : CirclePtr;


potom na základe príkazu

New(uKruznica);
je pre dynamický objekt vytvorený priestor v pamäti (v tzv. heape) a ukazovateľu je priradená adresa tohto priestoru. Ak obsahuje dynamický objekt virtuálne metódy, musí byť inicializovaný volaním konštruktora ešte pred volaním jeho metód:
uKruznica^.Init(600,100,30);
            Ako som spomínal, TP od verzie 5.5 rozširuje syntax procedúry New tak, že je možné vykonať alokáciu priestoru a inicializáciu dynamického objektu jediným príkazom:
New (uKruznica, Init(600,100,30));
            Kompilátor určí správnu metódu Init podľa prvého parametra. Ďalšia podoba funkcie New je:
uKruznica = New(CirclePtr);
kde v zátvorke je uvedené meno typu ukazovateľa. Funkčná podoba New môže mať aj druhý parameter konštruktor objektu:
uKruznica = New (CirclePtr, Init(600,100,30));
            Rozšírená syntax prispieva k lepšej čitateľnosti programu a má za následok kratší a efektívnejší kód.
            Rozšírená syntax sa týka aj procedúry Dispose, ktorá dovoľuje prostredníctvom druhého parametra špecifikovať množstvo pamäte, ktoré má byť uvoľnené. Dosiaľ sme zvyknutí používať procedúru Dispose takto:
type
   StringPtr = ^String;
var
   uRetazec : StringPtr;
 
   begin
     New(uRetazec);
     uRetazec^:='****************';
     Dispose(uRetazec);
   end.
            V tomto prípade odvodí procedúra Dispose veľkosť priestoru, ktorý má uvoľniť, z veľkosti hodnoty typu, na ktorý uRetazec ukazuje. Tá je pevne daná deklaráciou a v priebehu výpočtu sa nemení. Polymorfné objekty majú však neobyčajne premenlivú veľkosť. Z identifikátora ukazovateľa nemožno odvodiť veľkosť inštancie, na ktorú sa momentálne vzťahuje. Preto je potrebné mať nejaký mechanizmus, ktorý informáciu o veľkosti priestoru pamäte, ktorý má byť uvoľnený, procedúre Dispose poskytne. Týmto mechanizmom je mechamizmus deštruktora.
            Vieme, že deštruktorom sa nazýva špeciálna metóda, ktorá slúži na uvoľnenie pamäte dynamicky alokovaných objektov. Kľúčové slovo Destructor tejto metódy spôsobí, že pri jej vyvolaní generuje kompilátor dodatkový kód, ktorý vyberie z prvého slova tabuľky VMT zodpovedajúceho objektu informáciu o veľkosti objektu. Zistenú veľkosť inštancie odovzdá deštruktor procedúre Dispose takto:

Dispose(uKruznica, Done);
           
Samotné volanie dešruktora všeobecne nespôsobí uvoľnenie pamäte. Záleží na tom, ako je deštruktor zostavený. Metóda deštruktora môže byť volaná aj pre statické inštancie bez toho, aby došlo k nejakej chybe alebo kolízii. Napríklad

destructor Circle.Done;
begin
    Hide;
    end;
    ...
 
Kruznica.Done;
            V tomto prípade sa volanie deštruktora prejaví zmiznutím objektu z obrazovky. Žiadna pamäť nie je uvoľňovaná, netreba informáciu o jej veľkosti, deštruktor neurobí v tomto smere nič. Ale pretože zvyčajne je ťažké predpovedať, či nebude niekedy v budúcnosti potrebné, aby boli pôvodne statické objekty používané ako dynamické, je vhodné vybaviť každý objektový typ vlastným deštruktorom.
            Podobne ako iné metódy aj deštruktory môžu byť dedené. Deštruktory môžu byť statické aj virtuálne. Pretože však rôzne objektové typy vyžadujú rôzne deštruktory, odporúča sa, aby boli deštruktory vždy viruálne.
            Deštruktor môže byť aj prázdny:
destructor Figufe.Done;
begin
end;
Z praktických dôvodov mávajú niektoré objekty aj niekoľko deštruktorov.
Možno sa pýtate, prečo sa vôbec zaťažujeme takými vecami. Bohužiaľ, bez nich by sme nemohli pristúpiť ku skutočnému programovaniu v grafickom móde. A pripomínam, že Windows sú celé postavené na grafike.
Vráťme sa však k polymorfizmu.
Polymorfným objektom rozumieme objekt, ktorý môže v priebehu programu nadobúdať hodnoty svojich potomkov. Turbo Pascal dovoľuje s takýmito objektmi pracovať. Túto možnosť oceníme najmä v situácii, keď chceme vytvoriť objekt zložený z nejakých iných objektov. Pri práci na riešení našej úlohy jednoduchej animácie si takýto objekt, obrázok zložený z iných obrázkov, nazveme PieChart a stretneme sa s ním neskôr.
A aby ste nepovedali, že dnes nemáte nijaký zdrojačik, na listingu č. 1 je program, ktorý demonštruje polymorfné objekty. Využíva naše knižnice, takže ich musíte mať prístupné. Ako?
Ááále, to už predsa viete!
LISTING l
program PolymorphicObjectDemo;
uses Crt, Graph, MyFigure;
var Kruznica: Circle;
    Obluk: Arc;
    Elipsa: Ellipse;
    P: AFigure;
    r, FX, FY: integer;
    gd, gm: integer;
 
begin
gd := detect;
InitGraph(gd,gm,'');
Kruznica.Init(0,O,30);
Obluk.Init(O,O,40,120,420);
Elipsa.Init(0,0,20,50);
P := @Kruznica;
FX := 320;
FY := 240;
while not keypressed do
begin
r := random(lO);
if r=0 then P. = @Kruznica;
if r=l then P = @0bluk;
if r=2 'then P = @Elipsa;
FX := FX + random(9)-4;
FY := FY + random(9)-4;
PA.MoveTo(FX, FY);
delay(5OOO);
P'.Hide;
end;
  CloseGraph;
end.

 

Zobrazit Galériu

Nechajte si posielať prehľad najdôležitejších správ emailom

Mohlo by Vás zaujímať

Ako na to

Tipy a triky: Ako na snímku obrazovky na akomkoľvek počítači s Windows?

02.12.2016 00:13

Ak snímky obrazovky robíte často apotrebujete napríklad funkcie na posun stránok alebo snímanie zobrazenia pri vyššom rozlíšení displeja, zrejme používate nejakú špecializovanú aplikáciu. Väčšina použ ...

Ako na to 1

Tipy a triky: Ako aplikácii prednastaviť spúšťanie s administrátorskými právami?

30.11.2016 00:10

Väčšina aspoň trochu skúsenejších používateľov vie, že aj keď máte na operačnom systéme Windows vytvorený administrátorský účet, aplikácie pre bezpečnosť nefungujú vždy splnými administrátorskými práv ...

Ako na to 2

Tipy a triky: Ako vypnúť uzamykaciu obrazovku vo Windows 10?

29.11.2016 00:10

Rozčuľuje vás, že pred každým prihlásením doúčtu vášho počítača musíte prejsť uzamykacou obrazovkou? Windows 10 na tejto obrazovke ukazuje čas,dátum anejakú zaujímavú fotografiu zrôznych kútov sveta. ...

Žiadne komentáre

Vyhľadávanie

Kyocera - prve-zariadenia-formatu-a4-s-vykonom-a3

Najnovšie videá