Az objektum orientált programozás(Object Oriented Programming = OOP) három legfontosabb tulajdonsága:
Az Object Pascalban az objektum felhasználói típusként (CLASS osztály) jelenik meg, mellyel változókat,
objektum példányokat (instance) hozhatunk létre. A CLASS típus példányai
dinamikusan jönnek létre és minden új típusnak van elődje. Általában minden osztály adatmezőket
(field), metódusokat (methods) és jellemzőket (properties)tartalmaz.
Adatmező: az osztály minden obj. példányában megtalálható, kezelése és deklarálása a
rekordmezőével megegyező.
Metódus: az objektumon végzendő műveleteket definiáló eljárások és függvények. Azonos
osztályhoz tartozó objektumpéldányok a metódusokat közösen használják. A Self paraméter
jelöli, hogy éppen melyik példány adatmezőin kell műveletet végezni.
Kiemelt metódusok:
Osztály metódus: Az objektumpéldány helyett az osztályon fejti ki hatását, innen nem
elérhetők az adatmezők és a jellemzők.
Jellemző: Az osztály névvel ellátott attribútuma, melyre csak az olvasás és/vagy az írás
műveletét definiáljuk. A Delphi által támogatott komponens orientált programfejlkesztés alapját a
jellemzők képezik.
Komponensek: Olyan objektumok, melyeknek jellemzőik tervezési és futási időben egyaránt
elérhetőek.
Adatrejtés elve: Az objektum adatmezői és metódusai alaphelyzetben korlátozás nélkül
elérhetők, ez ellentmond az OOP adarejtési (data hiding) elvének. Általános szabály: az objektum
mezőit csak a metódusok felhasználásával érhetjük el. Az Object Pascalban ennek a szabálynak
úgy szerezhetünk érvényt, ha az objektum definícióját a unit inteface részébe tesszük, és a
private (belső), illetve public (külső) kulcsszavak segítségével kijelöljük az objektum részeit.
Az objektum protected kulcsszóval deklarált része private elérésű a külvilág számára, de ha
saját osztályt származtatunk a védett elemekkel rendelkező osztályból, akkor public elérésűvé
válnak az összetevők. Az osztályon belül a fenti kulcsszavakkal megjelölt részek tetszőleges
számban és sorrendben helyezkedhetnek el, de megkötés, hogy az adatok után a metódusok
következnek.
Az objektum példányai: Adott osztálytípussal több objektum példányt is létrehozhatunk. A
példányok saját adatterülettel rendelkeznek, de a metódusokat közösen használják. Az aktuális
objektumpéldány címét a Self paraméter adja, mely minden objektum utolsó nem látható
paramétere. Ezért metódus paramétereként nem használhatjuk a Self nevet, de metóduson
belül a Self használható a mezőhivatkozásban, vagy objektumok címének lekérdezésére.
Dinamikus helyfoglalású objektumpéldányok: Az objektum számára memóriaterületet
constructorral foglalunk és destruktorral szabadítjuk fel a foglalt területet. Osztály objektum
esetén a hagyományos new és dispose memóriakezelő eljárások nem használhatók.
Objektumok hierarchiája: Object Pascalban a származtatott osztálynak csak egyetlen
közvetlen őse lehet. Itt az egyedi osztályok helyett az egymásra épülő osztályok hierarchiája
biztosítja az objektumorientált megközelítés előnyeit.
Osztályok:
Ős osztály (ancestor), amiből az újat származtatjuk, származtatott osztály (descendant)
Tobject osztály: Ez az osztály előre definiált, ez minden osztály közös őse. Ha az osztály
deklarációjában elmarad az ős megadása, akkor az új típus automatikusan TObject lesz.
Sokoldalúság az osztály hierarchiában: Egy származtatott objektum tulajdonságainak
megváltoztatását virtuális és dinamikus metódusokon keresztül tudjuk megvalósítani. Tehát attól
függően, hogy a program futása során mely részén vagyunk az osztály hierarchiának, azonos
hivatkozás esetén más-más metódus kerül végrehajtásra, azaz a program futása során dől el,
hogy melyik metódust kell aktivizálni. Ez a jelenség a késői kötés, late binding, míg a fordítás
során megvalósított kötés az early bilding. A virtuális metódusokat tartalmazó osztályok esetén
a fordító virtuális metódustáblákat készít. (VMT Virtual Method Table) Ez a táblázat az
alapja a késői hivatkozás feloldásnak., mert a virtuális metódusok a VMT tábla alapján kerülnek
meghívásra. A virtuális metódusok hívása gyorsabb, de sok memóriát foglalnak a VMT táblázatok.
A dinamikus metódusok adattáblái láncot alkotnak és csak az adott osztályban definiált dinamikus
metódusokról tárolnak információt és a metódus belépési címét rendszerrutin keresi meg.
Osztályoperátorok: Az is operátort dinamikus típusellenőrzésre használjuk, segítségével
megtudhatjuk, hogy egy adott típusú objektum a megadott osztályhoz tartozik-e vagy sem. Az
as operátort típuskonverzió kijelölésére használjuk.
Üzenetkezelés: Üzenetkezelő metódusok segítségével mi magunk is fogadhatunk és
küldhetünk üzeneteket. Üzenetek fogadása Message direktívával deklarált üzenetfogadó metódussal.
Egy adott objektumnak az objektum Dispatch metódusával küldhetünk üzenetet.
Az objektum-orientált programozás (OOP) a 90-es évek uralkodó stílusirányzata, s egyre inkább
felváltja a - lassan már elavulttá váló, de ugyanakkor még klasszikusnak is számító - strukturált
programozást. Az objektum-orientált programozás jobban megközelíti, utánozza a
valóságot, és jobban igazodik a tárgyakhoz. Minden valóságos tárgyat nemcsak alakja, elhelyezkedése
jellemez, (Tehát nem csak a rá jellemző adatok -méretek-.) hanem az is, hogyan
viselkednek bizonyos körülmények között. Így a tárgyakat minden jellemzőivel együtt komplex
egészként tekintjük. (Azaz, az objektum az adatok és jellemzőjük komlpexe, elválaszthatatlan
egésze.) Amikor egy objektumot deklarálunk akkor írjuk le szerkezetét a mezőkkel,
másrészt azokat a szubrutinokat, amelyek leírják az objektum viselkedését. Az első magas
szintű programozási nyelv mely ezt tökéletesen támogatja, a Borland Pascal. Az objektumokat
a Pascal nyelv az 5.5-ös verziótól támogatja. Az 5.5-ös verzió még nem követte az objektumorientált
programozás elméletét, majd 6.0-ás verzió kezdte el kiegészíteni ezeket a hiányosságokat.
Az jelenlegi (7.0) verzió - szinte - tökéletesen igazodik az elmélethez, mind az öröklés,
a profilizmus, a zártság, a sokoldalúság és az adatrejtés elvét tekintve. Ezenkívül a Borland
Pascal nyelvhez tartozik - kiegészítésként - a Turbo Vision mely segít egy objektum-orientált
felhasználói felület kialakításában.
Az Objektumokról: Egy objektum négy fő részből áll ezek:
adatelemek, szerkezeti összefüggések, szelekciós műveletek, konstrukciós műveletek
Egy objektum négy fő tulajdonsága:
objektum = adat + kód (Ettől objektum, az objektum; mert e kettőnek elválaszthatatlan egészén
értjük az objektumot! )
Az objektum egyik alkotóeleme az adat, vagy adatszerkezet. Ez a rekordhoz hasonlóan deklarált
adatokat jelent. E részben tulajdonképpen a valóságot ábrázoljuk. (Úgymond: a tárgy méreteit)
A másik a kód, amelyen olyan eljárások és függvények összességét értjük, amelyek
leírják az objektum viselkedésmódját. Szintaktikája a rekordéval - majdnem teljesen - megegyezik,
a különbség annyi, hogy metódusokat - procedure-ákat, és function-öket - is deklarál(hat)unk.
Öröklés: (Egy egyszerű evolúciós példán keresztül.) A kétéltűekből származnak a hüllők. (A
biológia mai állása szerint.) A hüllők ugyanúgy rendelkeznek gerinccel, lábakkal, tüdővel ...,
mint a kétéltűek.
De rendelkeznek új tulajdonságokkal is pl: nincs szükség a vízre a peterakáshoz, -mint a
kétéltűeknél- az egyedfejlődés első szakaszában. Az objektumot leírva ez így néz ki:
TKeteltuek = Object(THalak)
Magassag, Súly: Type; {Ez maga az adat}
procedure Tulajdonsagok(); {ez a kód}
function Tulajdonsagok(): Type;
{esetleg még új adatok}
AzObjektumraJellemzőUjValtozó(k): Type;
end;
THullok = Object(TKeteltuek)
{Az örökölt metódusokat tartalmazza}
AzObjektumraJellemzoUjValtozo(k):Type
procedure Szaporodas;
{nem szükségeli a vizet a petelerakás, hiszen már lágy héjú tojást rak}
procdeure EgyedfejlodesElsoSzakasza;
{egyéb új metódusok}
end;
Profilizmus: Amint láttuk az új objektum (jelen esetben az új osztály) tartalmazza a
régi metódus(oka)t de helyette új utasítás sorozattal látjuk el. Így egy származtatott objektum
tartalmazhatja (használhatja) ugyanazt a metódust, de nem használhatja ugyanazt az objektumra
jellemző változók azonosítóit (neveit).
(Tehát: ugyanolyan nevű procedure-át, vagy function-t deklarálhatunk (azért, hogy felülírjuk
a régit), de ugyanolyan nevű változót nem. (Mivel azt már az ôs objektumban deklaráltuk. De
gondolkodjunk el rajta, hogy nem véletlenül nem lehet a változót újra deklarálni: hiszen az
objektum minden körülmény között ugyanolyan feltétel(ek) mellett fog létezni. (Illetve, így is
gondolkodhatunk -ez egy durvább megközelítés - : az utód súlyát sohasem fogjuk méter-ben
mérni, hanem mindig kilogramm-ban.)
Zártság: (A példát folytatva) Mivel a hüllők utódaik a kétéltűeknek minden tulajdonságukat
öröklik, így a kétéltűekre jellemző szaporodást, egyedfejlődést is, de rejtve marad mivel
helyette új szaporodás, ill. egyedfejlődés típus jött létre. Ugyanígy az objektumoknál, hiszen a
Profilizmus megengedte ugyanazt a metódust, (itt: életfunkciót) 'kicserélni' egy új metódusra.
!!!DE NE feledjük el, úgy ahogy a hüllőknél a saját szaporodás, ill. egyedfejlődés az elsődleges,
(azaz az új életfunkciónál a saját életfunkcióját 'hajtja' végre és véletlenül sem az örököltet) ugyanúgy az objektumoknál is, ahol szintén, a saját új metódus(ok) az elsődleges(ek).
Ezután a zártság két szálon fut tovább amit nem érdemes biológiai példán keresztül modellezni.
Az egyik szál - az öröklésre vonatkoztatva - a Statikus szál, a másik a Virtuális.
(Ezt a két különböző megoldási módot a metódusokra kell érteni, hiszen az adatok úgymond
állandóak.)
Statikus metódusok: az ilyen metódusok az örökléskor, csupán kicserélik az előd metódusát
az újra, nincs hatással az objektum más részeire - így nem változik meg teljesen annak tulajdonsága -
Gondolok itt az objektum más részében elhelyezkedő esetleg őt meghívó más metódusokra, akik nem
az újat hanem a régit fogják meghívni, a statikus megoldás következményeképpen.
Virtuális metódusok: Ilyen típusú metódusokkal lehet, megoldani az öröklés folyamaton
keresztül a sokoldalúságot. Ez azt jelenti, hogy nem csak a régi metódust cseréli ki az újra,
hanem az egész objektumot 'átnézve' a régi metódusra mutató összes hivatkozást átírja az új
metódusra mutatóvá. Ezáltal megváltozik az egész objektum tulajdonsága, és az öröklés folyamatra nézve sokoldalúvá válik.
Borland Pascalban leírás szintjén annyi a különbség, hogy a metódus után odabiggyesztjük a
virtual kulcsszót. (Figyelem, ha egy objektumban már használtuk a virtual kulcsszót akkor
annak utódaiban is kötelező.)
TValami = Object
{jellemző változók}
constructor Init;
procedure Valami(…); virtual;
function Valami(…): Type; virtual;
{egyéb metódusok}
end;
Ha egy objektumban használunk virtuális metódus(oka)t akkor használunk kell konstruktort.
(Ha az objektumban csak statikus metódus(ok) van(nak) akkor nem kötelező.) Ez egyenértékű
a procedure-ával, használata azért kötelező, mert ez hozza létre, a VirtuálisMetódusTáblát. Ha
nem hozzuk létre a VMT-t akkor programunk megállhat - kiakadhat -, lefagyhat, de leginkább
újraindítja számítógépünket.
Példa_a_Profilizmusra;
uses Objects;
type TElod = Object(TObject)
procedure Run;
end;
TUtod = Object(TElod)
procedure Run;
end;
procedure TElod.Run;
begin
WriteLn('Helló én a TElôd objektum vagyok!');
end;
procedure TUtod.Run;
begin
WriteLn('Helló én a TUtód objektum vagyok!');
end;
var Elod: TElod;
Utod: TUtod;
BEGIN
Elod.Run;
Utod.Run;
END.
Néhány szó a program magyarázatára: a TElod objektumot az ôs objektumból, a TObject
objektumból származtatjuk. (Származtathatnánk simán: TElod = Object formaként, de az előző
módon megfelel az OOP elméletének is.) A TElod objektum rendelkezik egy olyan Run metódussal
mely kiír egy sort. A TUtod objektum is rendelkezik egy ugyanolyan nevű Run metódussal, (a név
lehet ugyanaz hiszen a profilizmus megengedi!) ami hasonlóan kiír egy más
tartalmú sort a képernyőre. A program további részében az objektumokat írjuk meg, majd a
program végén lefuttatjuk őket.
Következő példaprogram a zártság elvét statikus módon próbálja bemutatni:
program Pelda_Zartsag_Statikus; procedure TElod.P1;
begin
uses Objects; P2;
end;
type
procedure TElod.P2;
TElod = Object(TObject) begin
constructor Init(A: Byte); WriteLn('X ', X);
procedure P1; end;
procedure P2;
private constructor TUtod.Init(A, B: Byte);
X: Byte; begin
end; inherited Init(A);
Y:=B;
TUtod = Object(TElod) end;
constructor Init(A, B: Byte);
procedure P2; procedure TUtod.P2;
private begin
Y: Byte; inherited P2;
end; WriteLn('Y ', y);
end;
constructor TElod.Init(A: Byte);
begin var U: Tutod;
X:=A; BEGIN
end; U.Init(1, 2);
U.P1;
{ a másik oszlopban folytatódik} END.
Ez a program talán már több magyarázatot igényel: először is van egy TElod objektum ami
rendelkezik Init, P1, P2 metódusokkal, és X privát változóval. (Private kulcsszó után álló metódusok,
és változók csak az objektumon belül használhatóak, a 'külvilág' számára közvetlenül nem érhetőek
el. Ez az adatrejtés elvéhez csatlakozik, mely azt jelenti, hogy az objektum
privát pl: változóit csak egy kívülről is elérhető metódussal kérdezzük le. A változókat (ill.
metódusokat) azért nem tesszük teljesen elérhetővé (Public=Publikussá), hogy illetéktelen ne
irogathassa át ezeket, esetlegesen károsítva az objektum működését. A metódusok egy részét
pedig azért szoktuk privátnak deklarálni, mert ezeket csak az objektum használja, másnak
'kívülről' nincs ill. nem lehet rá szüksége (, így elrejtjük azt - azokat) .
Ebbôl a TElod objektumból származik a TUtod objektum, mely örökli P1 metódusát, és X
privát változóját. A TUtod objektum a TElod objektumhoz hasonlóan rendelkezik egy Init
metódussal, mely új paraméterrel gyarapodott, egy P2 metódussal, melynek tartalma megváltozott, és egy
új privát Y változóval. Nézzük a TUtód objektum felépítését:
A barátok fogalma: Az objektum orientált programozás egyik jellemzője az öröklés. Ez
azonban nem mindig előnyös, mert erősen megkötheti kezünket. E probléma megoldására
találták ki a barátokat. A barátok beleláthatnak az adott objektumba úgy, mintha az adott
szinten az objektum részei lennének, viszont a barátság nem öröklődik. Az osztály leszármazottai
nem barátai a kérdéses elemnek.
Barátok lehetnek: