Objektový model Lazarus
Pre úspešné objektové programovanie v Lazarus je potrebné poznať a pochopiť objektový jeho model. Tento objektový model vychádza z objektového modelu Delphi, takže ak ho poznáte, máte vyhraté. Ak ho nepoznáte, čítajte ďalej.
Obsah článku
Objektový model Lazarus je založený na objektovom modeli Free Pascalu, doplneného o knižnicu vizuálnych komponentov. Táto knižnica vizuálnych komponentov je nazvaná LCL (Lazarus Component Library) a jej kompletné zdrojové kódy nájdete v adresári lcl svojej inštalácie Lazarus.
Základné pojmy
FreePascal je objektový programovací jazyk, čiže podporuje objektové programovanie. K základným pojmom objektovo orientovaného programovania patria pojmy ako objekt, trieda, dedičnosť, polymorfizmus a zapúzdrenie.
Deklarácia triedy
{ deklaracia triedy }
type
TNovaTrieda = class
premenna1: Integer;
premenna2: String;
procedure Vypis;
function Spoj;
end;
Objekty a triedy
Trieda je vlastne akýsi druh deklarácie typu, ktorá popisuje členy, metódy a vlastnosti triedy. Triedu možno deklarovať v rozhraní aj v implementačnej časti jednotky, ale jej metódy musia byť definované v implementačnej časti.
Objekt je dynamická inštancia triedy, ktorá obsahuje hodnoty všetkých členov deklarovaných v triede a v jej predkoch. Objekt je akousi obdobou premennej typu triedy. Pred použitím objektu musí byť deklarovaný a vytvorený. Za vytvorenie a uvoľnenie objektu je zodpovedný programátor.
Deklarácia a vytvorenie objektu
// deklarácia objektu
var myTrieda: TNovaTrieda;
// vytvorenie objektu
myTrieda := TNovaTrieda.Create;
Po tom, ako prestaneme objekt potrebovať, je potrebné ho z pamäte uvoľniť:
myTrieda.Destroy
takéto odstránenie objektu ho síce z pamäte uvoľní, ale teraz objekt myTrieda
ukazuje na neplatný popisovač, takže mu treba priradiť hodnotu nil
,
alebo objekt uvoľňovať pomocou FreeAndNil
:
FreeAndNil(myTrieda);
Zložky triedy a objektu
Vnútorná štruktúra triedy a objektu sa podobá na štruktúru typu záznam (record). Jednotlivé zložky objektu sú vlastne premenné, ktoré v sebe nesú informácie o danom objekte. Z hľadiska ich použitia možno tieto premenné rozdeliť na tri typy – členy, metódy a vlastnosti.
Členy
Člen objektu je doslova a do písmena premenná akéhokoľvek typu, ale z pohľadu Objektovo orientovaného programovania je použitie takýchto premenných – členov nesystémové, odporujúce zásadám OOP. Využíva sa len pre súkromné premenné, ktoré nie sú prístupné vonkajšiemu svetu. Identifikátory takýchto súkromných členov je zvykom pomenovávať tak, že začínajú písmenom f. K hodnotám súkromných členov objektov sa potom pristupuje pomocou vlastností.
Metódy
Metódy sú silným nástrojom tried a udávajú čo objekt robí. V podstate sa jedná o premenné procedurálneho typu, čiže vlastne o procedúry a funkcie, ktoré vykonávajú s objektom a jeho stavom nejakú činnosť.
Vlastnosti
Vlastnosti sú špeciálny druh členov a ich úlohou je uchovávať hodnoty premenných a riadiť prístup k nim. Je možné definovať vlastnosti, ktoré sú len na čítanie alebo naopak len na zapisovanie. Hodnotu vlastnosti môže vracať funkcia. Aj zápis do vlastnosti môže byť vykonávaný priamo alebo prostredníctvom metódy.
Dedičnosť
Dedičnosťou je v objektovo orientovanom programovaní nazývaná schopnosť odvodzovať nové triedy od už existujúcich tried. Odvodená trieda potom od existujúcej triedy dedí všetky jej členy, vlastnosti a metódy. Lazarus podporuje len jednoduchú dedičnosť, takže každá trieda môže mať len jedného predka, zvaného základná trieda. Táto základná trieda má zase svoju základnú triedu, atď. Týmto spôsobom triedy dedia členy, vlastnosti a metódy všetkých svojich predchodcov.
Základnou triedou nazývame bezprostredného predchodcu triedy, ktorý je určený v deklarácii triedy. Predchodcom je ktorákoľvek trieda v reťazci dedičnosti, vrátane základnej triedy. Zdedené vlatnosti, členy a metódy je možné prispôsobiť a rozšíriť ďalšími. To umožňuje vytvárať zložité triedy postupným pridávaním metód a vlastností v jednotlivých potomkoch, a tak zvýšiť efektivitu a zjednodušiť vývoj.
Potomok triedy
Type
TBod = class
x, y : integer;
constructor Create(X, Y : integer);
procedure Nastav_Bod(X, Y: integer);
end;
TKruh = class(TBod)
polomer: integer;
constructor Create(X, Y, r : integer); // prekrytie konštruktora
procedure Nastav_Polomer(r: integer);
end;
V uvedenom príklade deklaruje dve triedy TBod a TKruh a platí v ňom:
TKruh
je potomkomTBod
TBod
je základnou triedou preTKruh
TKruh
mení konštruktor triedyTKruh
pridáva definíciu metódyNastav_Polomer
TKruh
dedí odTBod
členyx
,y
a metóduNastav_Bod
Inými slovami, TKruh
zdedil všetky vlastnosti a metódy TBod
. Tieto
zdedené vlastnosti už nie je potrebné znova definovať, stačí ich
používať. Takto stred kruhu nastavíme volaním metódy TKruh.Nastav_Bod(X, Y)
,
ktorá je definovaná v predkovi, teda v triede TBod
.
Polymorfizmus
Polymorfizmus (mnohotvárnosť) je to čo objektovému programovaniu pridáva skutočnú silu. Podstata tejto vlastnosti je v mechanizme zdieľania metód, teda že odvodené triedy (potomkovia) môžu nie len používať metódy predka, ale môže aj meniť ich funkčnosť.
Polymorfizmus teda znamená, že meno metódy bude rovnaké v rôznych stupňoch hierarchie tried, ale môže byť pre každú triedu definovaná inak.Zobermesiopäť triedy TBod a jej potomka TKruh .
Prepísané metódy
Type
TBod = class
polomer: integer;
constructor Create(X, Y, r : integer); // prekrytie konštruktora
procedure Nastav_Bod(X, Y: integer);
procedure Ukaz; virtual;
procedure Skry; virtual;
procedure Posun(dx, dy: Integer);
end;
TKruh = class(TBod)
x, y : integer;
constructor Create(X, Y : integer);
procedure Nastav_Polomer(r: integer);
procedure Ukaz; override;
procedure Skry; override;
end;
Mechanizmus posunu je možné definovať v metóde Posun
triedy TBod
,
napríklad najprv volaním metódy Skry
, potom zmenou súradníc
Nastav_Bod
a nakoniec opätovným nakreslením metódou Ukaz
:
Metóda TBod.Posun
procedure TBod.Posun(dx, dy:Integer);
begin
Skry;
Nastav_Bod;
Ukaz;
end;
Keďže sú metódy Skry
a Ukaz
definované ako virtuálne metódy, možno ich
správanie zmeniť (nanovo ich definovať) v triede potomka. Takže metóda
TKruh.Skry
definuje skrytie (zmazanie) nakresleného kruhu a už nie
bodu. Obdobne metóda TKruh.Ukaz
zabezpečí nakreslenie kruhu.
Možno vás napadá, načo sú nám metódy Skry
a Ukaz
v triede TBod
? Sú
zdánlivo zbytočné, pretože nedáva zmysel skrývať a kresliť bod (vo
svojej podstate neexistuje). Ale práve ich definícia v tejto triede
umožňuje ich použitie v metóde TBod.Posun
. A to nám zase umožňuje
metódu Posun
zdediť v potomkovi, bez toho aby sme ju akokoľvek
upravovali. Polymorfizmus sa postará o volanie metód Skry
a Ukaz
z tej
„správnej” triedy, takže metóda Posun
bude posúvať kruh, ak je volaná z
triedy TKruh
a bod pri volaní z triedy TBod
.
Zapúzdrenie
Zo zapúzdrením sa stretávame v často i v bežnom živote. Jedná sa o skrytie vlastnej funkcie nejakého stroja (objektu). Dajte si ruku na srdce a odpovedzte úprimne do akej miery viete ako je skonštruovaný Váš diaľkový ovládač? Na druhej strane, potrebujete to vedieť? Nie nepotrebujete, stačí vedieť ktoré gombíky kedy stláčať (rozhranie ovládača).
Zapúzdrenie v objektovo orientovanom programovaní zaručuje, že nikto nemôže priamo pristupovať k vnútru iných objektov. Každý objekt navonok sprítupňuje len rozhranie, pomocou kterého (a nijak inak) možno s objektom pracovať. So zapúzdrením úzko súvisia prístupové úrovne jednotlivých členov, vlastností a metód objektu. V Lazarus možno pracovať so štyrmi úrovňami prístupu:
private
– súkromné deklarácie - prístup majú len metódy vlastnej triedy a procedúry a funkcie deklarované v rovnakej jednotke,protected
– chránené deklarácie - môžu ich využívať metódy vlastnej triedy alebo jej potomkov,public
– voľne prístupné deklarácie, na komunikáciu triedy s okolím,published
– podobné ako verejné, ale umožňujú spolupracovať s Inšpektorom objektov.
Prístup k metódam a vlastnostiam
type
TMojaTrieda = class
private
{ Private declarations }
protected
{ Protected declarations }
public
{ Public declarations }
published
{ Published declarations }
end;