Image
8.6.2016 0 Comments

Stretnutie s Pascalom II. /1. časť

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

Poďme sa venovať programovaniu, ktoré sa nazýva objektovo orientované programovanie, skrátene OOP. Vlastne to ani nie je také nové, princípy boli položené už v roku 1967 (Zdá sa to neuveriteľné, ale je to tak!), ale mnohým z nás to bude pripadať ako nové, zvláštne, zložité, nepochopiteľné a nepotrebné... Pravda, je to zložité, ale pochopiť sa dá (časom), navyše to budeme potrebovať, ak chceme písať už spomínané veľké a zložité projekty, ale hlavne ak chceme začať programovať vo Windows. Preto si spolu prejdeme základy OOP a potom sa rozdelíme na dva smery:

– tí, čo zostanú verní DOS-u, sa budú venovať tzv. TURBO VISION (TV), čo je mocný nástroj na programovanie veľmi zložitých projektov, ako je účtovníctvo, databázové projekty, skladové hospodárstvo, cestovné poriadky a pod. TV je postavené na objektoch, je súčasťou programovacieho balíka Turbo Pascal 6 a 7. Čo TV dokáže, to vidieť hneď, lebo prostredie TP je napísané v samotnom Turbo Vision. Tento kurz povedie môj priateľ a výborný pascalista - objektista Štefan Stieranka.

– my, čo by sme si chceli vyskúšať, ako chutia Windows a programovanie v nich, sa stretneme s Delphi, novým programovacím produktom, svetovou jednotkou firmy BORLAND, postavenou na Turbo Pascale, v ktorom sa dá aj s minimálnymi základnými znalosťami programovania v TP vytvoriť dobrý program.

História OOP

OOP sa považuje za najmodernejšiu a najprogresívnejšiu programátorskú techniku. Prvé princípy boli použité v jazyku SIMULA 67 (67 je rok vzniku), a teda skutočne nie sú nové, ich masové rozšírenie umožnila až firma BORLAND so svojím Turbo Pascalom verzie 5.5.

Tento dobrý nápad bol rozpracovaný vo verzii 6.0, kde vzniklo aj spomínané Turbo Vision. V súčasnosti je na trhu Turbo Pascal 7.0 s Turbo Vision 2.0 a ich windowsovská implementácia Delphi. Ako už samotný názov prvého objektovo orientovaného jazyka SIMULA naznačuje, bol určený na vytváranie programov simulujúcich a modelujúcich niektorý konkrétny jav. Teda pôvodným zmyslom vzniku metód OOP bola simulácia a modelovanie.

Nejde len o techniku programovania, je to celá programátorská filozofia, myslenie odpozorované z reálneho. Preto ak chceme pochopiť OOP, musíme zabudnúť na štruktúrované princípy (ale nie úplne) a snažiť sa porozumieť objektom.

Základné princípy OOP

Základným pojmom v OOP je objekt. Môžeme ho chápať ako abstrakciu objektu z reálneho sveta. A aby sme nechodili ďaleko, taký reálny objekt máme na stole. Budeme hovoriť o počítačoch. Počítač je (ne)vďačný objekt, ktorý má určité vlastnosti, napr. šírku zbernice a veľkosť operačnej pamäte, no má aj určité schopnosti, napr. vie počítať alebo pípať.

Objekt v zmysle OOP je akýmsi rozšírením dátového typu záznam (record), ktorý už dávno poznáme. Ten umožnuje vyjadriť obidva uvedené typy charakteristík. Vlastnosťou je šírka zbernice a veľkosť pamäte, ktoré sú prezentované dátovými položkami rovnako ako vo zvyčajnom zázname. Schopnosti sú opísané procedúrami, v OOP nazývanými metódy, ktoré sú súčasťou objektu.

Toto už klasický záznam neumožňoval. V Turbo Pascale môžu byť metódami tak procedúry, ako aj funkcie. Potom môžeme počítač zadefinovať ako objekt takto:
Pocitac = object
sirka_zbernice : (rozna, 8, 16, 32, 64);
velkost_pamate : string;
procedure Pipni;
procedure Pocitaj;
end;


            Týmto zápisom sme zaviedli triedu (class) objektov, nazvanú Pocitac. V terminológii OOP všetky objekty s rovnakými vlastnosťami patria do jednej triedy. Opis triedy teda zodpovedá definícii typu. Konkrétna realizácia objektu triedy daného typu (vlastne pamäťová premenná) sa v slovenskej (anglickej) terminológii nazýva inštancia (instance).
            Vidíme, že OOP umožňuje združovať logicky súvisiace dáta a kód (metódy), ktoré s týmito dátami pracujú. Hovoríme, že dáta aj metódy sú vnútri objektu zapuzdrené a táto vlastnosť sa nazýva zapuzdrenie alebo encapsulation. Táto vlastnosť OOP je prvým z troch najdôležitejších princípov celej filozofie OOP.
            Teraz si predstavme, že pred nami stojí ZX Spectrum (ach, zlatý Sinclair...) a átečko. Čo o nich môžeme povedať? Ide o dva počítače, majú teda určitú šírku zbernice a veľkosť pamäte, pípajú a vedia počítať. Zároveň sú však každý iný. Spectrum bol skonštruovaný na hry, ale pracovať s programami typu CAD by sa s ním asi nedalo, zatiaľ čo átečko je určené na serióznu prácu, ale spúšťať na ňom iba hry by bolo zbytočným prepychom. V OOP by sme naznačenú situáciu opísali takto:


Sinclair = object (pocitac)
procedure Hraj_Hry;
end;
Atecko = object (pocitac)
procedure Konstruuj;
end;


            Objekty Sinclair a Atecko teraz majú všetky vlastnosti a vedia všetko to, čo vie objekt pocitac. Každý z nich však vie oproti počítaču navyše niečo, čo nevie ten druhý. Objekt pocitac sa nazýva predok (ancestor), objekty Sinclair a Atecko sú potomkovia (descendant). Opísaná črta, spočívajúca v odovzdávaní vlastnosti predka potomkovi sa rovnako ako v živote nazýva dedičnosť (inheritance). Je to druhý základný princíp OOP.
            Predstavme si, že počítanie, teda metódu Pocitaj budeme na počítači simulovať tak, že na obrazovku PC budeme vypisovať parametre toho-ktorého počítača. Vypisovanie realizujeme zvláštnou metódou Urci_Typ_procesora. Túto metódu bude využívať metóda Pocitaj na simuláciu výpočtu. Definíciu objektu teda rozšírime:


pocitac = object
          sirka_zbernice : (rozna, 8,

16, 32, 64);
          procedure Urci_Typ_procesora;
          procedure Pipni;
          procedure Pocitaj;
end;

 

a kód pre metódu Pocitaj bude obsahovať volanie metódy Urci_Typ_procesora:

 

procedure Pocitaj;
begin
.
.
.
Urci_Typ_procesora;
.
.
.
end;

 

Čo sa teraz stane, ak použijeme metódu Pocitaj pre inštanciu objektu Sinclair a rovnakú metódu pre objekt Atecko?

Predpokladáme, že triedy Sinclair a Atecko sú potomkovia novo nadefinovanej triedy objektov Pocitac. Odpoveď znie: na obrazovke uvidíme výpis - typ procesora, šírku zbernice a veľkosť pamäte, ale nebude to ani Sinclair, ani átečko.

Lenže čo vtedy, ak chceme, aby sa výpisy líšili a zodpovedali typu počítača? Postačí, ak nadefinujeme v objektoch Sinclair a Atecko vlastnú metódu Urci_Typ_procesora? Nie, situácia sa ani týmto krokom veľmi nezmení. Ak vyvoláme teraz metódu Urci_Typ_procesora z inštancie objektu Sinclair, vypíše sa na obrazovku typ Z80. Ak vyvoláme z tej istej inštancie metódu Pocitaj, bude sa opisovať všeobecný počítač.
            Je to preto, lebo všetky metódy boli definované ako statické, a tak došlo k tzv. včasnej väzbe (early binding). To znamená asi toľko, že prekladač predpokladá, že pozná všetky okolnosti už v dobe prekladu a vygeneruje kód, kde je v metóde Pocitaj natvrdo volaná metóda Urci_Typ_procesora z triedy Pocitac. Riešením je použitie mechanizmu polymorfizmu (tretí princíp). Navonok sa to prejaví tak, že metóda Urci_Typ_procesora bude vo všetkých triedach definovaná ako virtuálna:

 
pocitac = objekt
         .
         .
         .
procedure Urci_Typ_procesora;
virtual;
procedure Pocitaj;
         .
         .
         .
end;
 
Sinclair = object (pocitac);
         .
         .
         .
procedure Urci_Typ_procesora;
virtual;
         .
end;
 
Atecko = object (pocitac);
         .
         .
procedure Urci_Typ_procesora;
virtual;
         .
end;


            Teraz bude všetko pracovať podľa predpokladov. Prekladač totiž po tom, čo zistil, že sa použila virtuálna metóda, vytvoril pre každú z nadefinovaných tried objektov tzv. tabuľku virtuálnych metód (TVM). V kóde metódy Pocitaj teraz nie je priamy skok na kód metódy Urci_Typ_procesora, ale volanie sa uskutoční odkazom do tejto tabuľky. Až pri behu programu sa zistí, do tabuľky ktorej triedy sa má siahnuť po adresu metódy Urci_Typ_procesora. Toto je stručný opis mechanizmu neskorej väzby (late binding).
            Z neho je možné odvodiť, že ak je metóda v predkovi definovaná ako virtuálna, musí byť virtuálna aj vo všetkých potomkoch. Toto možno chápať ako súčasť syntaktických pravidiel jazyka, ktoré si ešte preberieme podrobnejšie.
            Na listingu č. 1 je výpis zdrojového textu programu OOP1.PAS. Môžete si ho skúšať a ladiť, zmeňte virtuálne metódy na statické jednoduchým zmazaním slova virtual, preložte a sledujte jeho správanie. Mnoho vecí sa vám objasní. Zásady pri písaní takýchto programov, ako aj tento konkrétny program si podrobnejšie vysvetlíme nabudúce.

Listing 1:

program OOP;

uses crt;

type tbity = (rozna, osem,

sestnast, tridsatdva, sestde-

siatstyri) ;

(*********)

pocitac = object

sirka__zbernice : tbity;

velkost_pamate : string;

constructor

Init(abity:tbity;pamat :

string);

procedure Pipni;

procedure Urci_Typ_procesora;

virtual;

procedure Pocitaj;

end;

Sinclair = object (pocitac)

procedure Urci_Typ_procesora;

virtual;

end;

atecko = object (pocitac)

procedure Urci_Typ_procesora;

virtual;

destructor Done;

end;

patecko = ^atecko;

styri86 = object (pocitac)

procedure Urci_Typ_procesora;

virtual;

end;

Pentium = object (pocitac)

procedure Urci_Typ_procesora;

virtual;

end;

(*********)

constructor

pocitac.Init(abity:tbity;pama

t : string);

begin

sirka_zbernice := abity;

velkost_pamate := pamat;

end;

procedure Pocitac.Pipni;

begin

write(#7);

delay(5O) ;

write(^G);

end;

procedure

Pocitac.Urci_Typ_procesora;

begin

write(‘ rôzny ‘);

end;

(*********)

procedure Pocitac.Pocitaj;

var ch : char;

procedure Vypis;

begin

write(‘Typ procesora : ‘);

Urci Typ_procesora;

write(‘; Zbernica : ‘)';

case sirka_zbernice of

rozna : write(‘rozna ‘);

osem : write(‘ 8 ‘) ;

sestnast : write(‘ 16 ‘);

tridsatdva : write(‘ 32 ‘);

sestdesiatstyri : write(‘ 64

‘);

end;

write(‘ bitov; Pamat : ‘);

writeln(velkost_pamate);

end;

begin

Vypis;

Pipni;

delay(5OOO);

end;

(*********)

procedure

Sinclair.Urci_Typ_procesora;

begin

write(‘ Z80 ‘);

end;

procedure

atecko. Urci_Typ_procesora;

begin

write(‘ 80286 ‘);

end;

destructor atecko.Done;

begin

end;

procedure

styri86.Urci_Typ_procesora;

begin

write (‘ 80486 ‘) ;

end;

procedure

Pentium.Urci_Typ_procesora;

begin

write(‘ Pentium ‘);

end;

(*********)

var pcl : pocitac;

pc2 : Sinclair;

pc3 : patecko;

pc4 : Styri86;

pc5 : Pentium;

 

BEGIN clrscr;

pcl.Init(rozna,´lubovolna´);

pc2. Init (osem,´64 Kb´) ;

pc3:=New(patecko,Init(ses-tnast, ´l MB´));

pc4.Init(tridsatdva,´ 4 MB´);

pc5.Init(sestdesiatstyri,´32

MB´);

pcl.Pocitaj;

pc2.Pocitaj;

pc3^.Pocitaj;

pc4.Pocitaj;

pc5.Pocitaj;

Dispose(pc3,done) ;

END.

 


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á