absztrakt adatt pusok n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
Absztrakt adattípusok PowerPoint Presentation
Download Presentation
Absztrakt adattípusok

Loading in 2 Seconds...

play fullscreen
1 / 66

Absztrakt adattípusok - PowerPoint PPT Presentation


  • 123 Views
  • Uploaded on

Absztrakt adattípusok. kAkAÓ 2004. Objektumorientált programozás. In: Nyékyné Gaizler Judit (szerk.): Programozási nyelvek, Kiskapu, Budapest, 2003. pp.333-350. A programozási nyelvek fontos feladata a használt programozási módszertanok aktív támogatása. Elvárások a programnyelvekkel szemben:

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Absztrakt adattípusok' - gudrun


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
absztrakt adatt pusok

Absztrakt adattípusok

kAkAÓ 2004.

Objektumorientált programozás. In: Nyékyné Gaizler Judit (szerk.):Programozási nyelvek, Kiskapu, Budapest, 2003. pp.333-350.

slide2

A programozási nyelvek fontos feladata a használt programozási módszertanok aktív támogatása. Elvárások a programnyelvekkel szemben:

1. Modularitás: az egyes típusokat önálló fordítási egységekben lehessen megvalósítani. Ezek legyenek újrafelhasználhatóak, fejleszthesse más-más ember őket.

2. Egységbezárás (encapsulation): a nyelv kezelje összetartozó egységként a típusértékhalmazt és műveleteit.

3. Az ábrázolás elrejtése: az adott típus használója csak a specifikációban megadott tulajdonságokat használhatja ki. Ezért lehet változtatásokat végrehajtani úgy, hogy az ne érintse a hierarchia más lépcsőit.

4. A specifikáció és az implementáció szétválasztása külön fordítási egységbe lehetővé teszi, hogy az adott típust használó más modulok a típusspecifikáció birtokában elkészíthetők, függetlenül a megvalósítástól.

slide3

5. A modulfüggőség kezelése: a fordítóprogram maga kezelje a modulok közötti kapcsolatokat (egyik használja a másikat stb.)

6. Konzisztens használhatóság: a felhasználói és beépített típusok ne különbözzenek a használat szempontjából.

7. Általánosított programsémák támogatása: a programozó minél általánosabban írhassa meg programjait. A nyelv adjon lehetőséget az ismétlések minimalizálására, mert ez javítja a kód olvashatóságát és karbantarthatóságát.

slide4

Modularitás. A modern nyelvekben a modulokra bontás alapja a típusokra bontás, azaz egy modul egy típust valósít meg. A modulok határai gyakran a láthatósági határokat is jelentik, gyakran a modulok kifelé korlátozzák a bennük definiált adatok láthatóságát.

Egységbezárás. Lényege, hogy a típusokat a rajtuk értelmezett műveletekkel együtt, egységként használja. Azok az az alprogramok jogosultak egy típus belső szerkezetéhez hozzáférni, amelyek a típus műveleteit valósítják meg, azaz részei az egységbezárásnak. Az ún. öröklődés során a származtatott típus örökli az őstípus primitív műveleteit (ezek azok, amelyek a típussal „egységbe vannak zárva”). A C++-ban például ezek a műveletek az osztály névterében definiált műveletek.

slide5

Az ábrázolás elrejtésének támogatására a nyelvek az összetett típusok komponenseinek láthatóságát gyakorta szintekre bontják, amely szintek meghatározzák, hogy pontosan kik férhetnek hozzá az adott komponenshez. Persze nem minden nyelvben: például C, Pascal vagy Modula nem rendelkezik ilyen szabályozással.

Általában 3 szintet szoktak az OOP nyelvekben megkülönböztetni:

Nyilvános (public) – az adott komponens mindenki számára hozzáférhető

Védett (protected) – az adott komponens csak a leszármazottak számára látható (csak az öröklődést támogató nyelvekben)

Privát (private) – az ábrázolás teljesen rejtett része, csak a műveletek megvalósításában használható komponensek.

Ezt a 3 szintet használja pl. az ADA 95 vagy a C++, a Java és az Eiffel több szintet tesz lehetővé.

slide6

A típusspecifikáció és a megvalósítás szétválasztása külön fordítási egységbe az alábbi előnyökkel jár:

  • Segít abban, hogy az egyes modulok egymástól függetlenül elkészíthetőek legyenek,
  • A típus használatához szükséges összes információ elkülönülten is rendelkezésre áll, így a megvalósítás lefordított állapotban is szállítható.
  • Ha a specifikációt és az implementációt két fordítási egységre bontjuk szét, gondoskodni kell arról, hogy csak a specifikációs rész birtokában a fordító program képes legyen a szükséges memóriafoglalást meghatározni.
  • C és C++ fejállományok (header fájlok)
  • A C/C++ nyelvekben a specifikációt fizikailag be kell másolni minden olyan fordítási egysége, amely az adott típust használni akarja. A specifikáció egy külön speciális forrásfájlban (header fájl) leírható, és ezt az előfordító emeli be a megfelelő fordítási egységbe.
slide7

A programok legmagasabb szintű építőkövei a modulok. A programok működése ezen modulok interakciója. Minden modul igényel szolgáltatásokat és segítségükkel más szolgáltatásokat valósít meg. A modulok között egyfajta függőség alakul ki, például egy megváltozott modul miatt más modulok újrafordítása is szükségessé lehet.

C++-ban ennek a kezelése a programozó feladata: minden fordítási egységet a programozónak külön kell kezelnie. Erre való a make. Maga a nyelv azonban nem nyújt támogatást.

Az ADA nyelvben a with segítségével meg lehet adni, hogy a szóbanforgó modul milyen más fordítási egységektől függ. Így a modul lefordítása előtt mindazon modulok specifikációs részének lefordítására sor kerül – ha szükséges – amelyektől ez a modul függ.

slide8

Azonosító túlterhelése (overloading). Egy azonosító túlterhelése azt jelenti, hogy a programszöveg egy adott pontján az azonosítónak több definíciója is érvényben van. Ilyenkor a fordító a hivatkozási környezetből dönti el, hogy a több lehetséges értelem közül melyiknek megfelelően használja az adott azonosítót. Példa: a + operátor mást jelöl a 3+4 illetve a 3.13+4.2 kifejezésekben. A fordítóprogram ilyenkor az operandusok típusa alapján határozza meg, hogy a + műveletnek mit kell csinálnia.

Csinálhat-e ilyet a programozó is? Azaz lehetséges-e, hogy egy, a programozó által definiált azonosító egyszerre több definícióval bírjon, melyek közül a fordító az argumentumok típusa alapján választja ki a ténylegesen végrehajtandó példányt.

Nem számít túlterhelésnek, ha egy leszármaztatott osztály megváltoztatja egy ősosztályban deklarált művelet definícióját: ezt felüldefiniálásnak nevezzük. Ebben az esetben a hivatkozáshoz tartozó tényleges definíció nem fordítási időben (statikusan), hanem futási időben (dinamikusan) választódik ki. Ezt a jelenséget dinamikus összekapcsolásnak nevezzük (late binding).

slide9

A túlterhelés speciális esete az operátor túlterhelés, amikor egy nyelv operátorait (+, –, *, /, = , <, >, sizeof, new stb.) terheljük túl. Ha pl. definiálunk egy mátrix típust, szeretnénk a mátrixok szorzását is *-gal jelölni.

t pussal val param terez s

Típussal való paraméterezés

kAkAÓ 2004.

Objektumorientált programozás. In: Nyékyné Gaizler Judit (szerk.):Programozási nyelvek, Kiskapu, Budapest, 2003. pp.353-388.

slide11

A programfejlesztés során gyakran merül fel annak igénye, hogy általánosan megfogalmazott, széles körben alkalmazható megoldásokat adjunk.

Megfelelő paraméterek megválasztásával az alprogramok erre lehetőséget adnak. Az alprogramok paraméterei nem lehetnek típusok, pedig a különféle típusokon megadott hasonló feladatokat hasznos lenne egyetlen alprogrammal megoldani.

A típusparaméterrel ellátott alprogramokat polimorfnak, azaz többalakúnak nevezzük. Előfordulhat az is, hogy a különböző típusokhoz különböző implementáció tartozik.

Példa: különböző alaptípusú tömök rendezése egyetlen rendező alprogrammal, amely az elemtípussal van paraméterezve.

slide12

C++-ban a template szerkezettel lehet megoldani a feladatot:

template <classElem>

voidrendez(vector<Elem>& v){

constsize_tn=v.size();

for (intgap=n/2; 0<gap; gap /= 2;{

for (inti=gap; i<n; i++){

for (intj=i – gap; 0<=j; j – =gap){

if (v[j+gap]<v[j]){

Elem temp=v[j]; v[j]=v[j+gap]; v[j+gap]=temp;

}

}

}

}

}

Shell rendezés tetszőleges Elem elemtípusú tömbre

Elem helyére írhatunk például int-et

Ha egész számokat kívánunk rendezni, vector<int> v; rendez(v); kell.

objektumorient lt programoz s

Objektumorientált programozás

kAkAÓ 2004.

Forrás: Objektumorientált programozás. In: Nyékyné Gaizler Judit (szerk.):Programozási nyelvek, Kiskapu, Budapest, 2003. pp.391-456.

slide14

A számítógépes programok segítségével az ember a valós világot próbálja modellezni. Az objektumorientált szemlélet a valóság megközelítésének és ábrázolásának egy módszere. A modellezés során a valós tárgyakat objektumokkal ábrázolja,, amelyeket állapotukkal (adataikkal) és metódusaikkal jellemez.

Az OO megközelítés egy programozási szemléletmód, amelynek alapján rendszerfejlesztési módszertanokat is kidolgoztak. Ezek a módszertanoka teljes fejlesztési folyamatot átfogják:

Analízis, Tervezés, Implementálás, Tesztelés, Karbantartás.

slide15

Az analízis során a rendszert együttműködő objektumok összességeként modellezzük, a tervezés és az implementáció ezen objektumokat alakítjuk ki.

Objektumorientáltnak nevezünk egy programot, mely egymással kapcsolatot tartó objektumok összessége, ahol minden objektumnak megvan a jól meghatározott feladata.

A modellezés során az ember olyan gondolatmenetet használ, amelynek segítségével elvonatkoztat, megkülönböztet, osztályoz, általánosít, vagy leszűkít, részekre bont, kapcsolatokat épít fel.

slide16

Az absztrakció az a szemléletmód, amelynek segítségével a valós világot leegyszerűsítjük úgy, hogy csak a cél elérése érdekében feltétlenül szükséges részekre koncentrálunk.

Az objektumok a modellezendő valós világ egy-egy önálló egységét jelölik. Meghatározza őket belső állapotuk és a nekik küldhető üzenetekre való reagálásuk. A reagálás során az objektum belső állapota megváltozhat, illetve valamilyen műveletet végez, üzenetet küldhet más objektumoknak.

Az objektumokat kategorizáljuk, a hasonlókat egy osztályba soroljuk. Az osztályozás az általánosítás és a specializálás segítségével történik: az objektumok között hasonlóságokat és különbségeket keresünk.

slide17

Az osztályozás az emberi gondolkodás szerves része. Az ugyanolyan fajta adatokat tartalmazó, és az ugyanolyan viselkedés-leírással (metódusokkal) rendelkező objektumokat egy osztályba soroljuk. Az objektum-osztályok hordozzák a hozzájuk tartozó objektumok jellemzőit.

Minden objektum valamilyen osztály példánya (instance), rendelkezik osztályának sajátosságaival, átveszi annak tulajdonságait az adatszerkezetekre és a műveletekre vonatkozóan.

Az objektum tehát adatok (attribútumok) és műveletek (metódusok) összessége, ez utóbbiak elvégzik az objektumra szabott feladatot vagy leírják az objektum viselkedését.

Attribútum a művészetben: ha egy templomi festményen valaki kulcsot tart a kezében, akkor az Péter apostol, és a művelet a kezében tartás.

slide18

Az objektumoknak mindig van belső állapotuk – ezt az adatok pillanatnyi értékei jellemzik. Metódushívások után az objektumok állapota meg változhat. Az objektumok emlékeznek állapotukra és a feladatvégzési folyamat mindig egy alapértelmezett kezdőállapotból indul, és egy másik állapotba megy át. A következő állapotátmenetnél onnan folytatja a folyamatot, ahol előzőleg abbahagyta.

A kapcsolatban álló objektumok kommunikálnak egymással. Ez üzenetküldés formájában történik. Az üzeneteket kívülről elérhető metódushívásokkal ábrázoljuk. Az üzenetet a megszólított objektum azonosítójával minősítjük, és lehetnek paraméterei:

Obj.Üzenet (Paraméterek)

slide19

Ha az objektumtól valamilyen választ várunk az üzenetre, akkor ezt a változó paramétereken keresztül vagy a metódus visszatérési értékeként kaphatjuk meg.

A következőkben megnézzük, hogyan hozhatók létre osztályok és objektumok egyes programozási nyelvekben.

slide20

SIMULA 67

ClassTeglalap(TeglNev, Szelesseg, Magassag); ! Osztály 3 paraméterrel

TextTeglNev; RealSzelesseg, Magassag; ! Paraméterek specifikációja

Begin

RealTerulet, Kerulet; ! Attribútumok;

ProcedureFrissit; ! Művelet;

Begin

Terület := Szelesseg * Magassag;

Kerület := 2*(Szelesseg + Magassag);

End ofFrissit;

ProcedureKiir; ! Művelet;

Begin

OutText(”I am a Teglalap”); OutText(TeglNev);

OutText(”Terulet: ”); OutFixText(Terulet,2,7);

OutText(”Kerulet: ”); OutFixText(Kerulet,2,7);

End ofKiir;

Frissit; ! Teglalap élete;

Kiir;

End ofTeglalap;

Létrehozás:

newTeglaLap(„Kicsi”,2,3)

slide21

SMALLTALK

A SMALLTALK-ban minden objektum, még az osztályok is. Ez azt jelenti, hogy az osztályoknak is vannak adattagjaik és metódusaik. Hozzunk létre egy Szamla osztályt egy Egyenleg nevű adattaggal.

Object subclass: #Szamla

instanceVariableNames: ‘egyenleg’

classVariableNames: ‘’

poolDictionaries: ‘’

Category: nil !

slide22

C++ -ban egy új osztályt így deklarálhatunk:

class Teglalap{

int x, y;

public:

void ertekadas (int, int);

int terulet() { return (x*y); }

};

A Teglalap osztály két rejtett adattagja x és y. Két nyilvános metódusa van, az értékadó és a terület számító metódus. A területszámító metódust az osztály deklarációjában definiáltuk.

Az értékadást az osztálydeklaráción kívül, a baloldalt látható módon adhatjuk meg.

void Teglalap::ertekadas(int x1, int y1){ x = x1; y = y1; }

slide23

A Teglalap osztály egy új tagjának létrehozása C++-ban statikus illetve dinamikus helyfoglalású változóként:

Teglalap haz; // statikus helyfoglalású példány

haz.ertekadas(5,3);

int thaz = haz.terulet(); // thaz = 15

Teglalap * kert = newTeglalap; // Dinamikus helyfoglalású példány

kert ->ertekadas(20,17);

int tkert = kert->terulet(); // tkert = 340

slide24

Az Object Pascalban egy új osztályt szintén a class kulcsszó segítségével hozhatunk létre:

type

TDatum = class

private Ev, Honap, Nap : integer;

public

procedureBeallit (e,h,n: integer);

functionSzokoev: boolean;

end.

Az objektum példányok létrehozása dinamikusan történik, ellentétben a Turbo Pascallal, a változó deklarálása után meg kell hívnunk az osztály konstruktorát, amely lefoglalja és inicializálja a szükséges memóriaterületet (Create). A használat befejeztével a memóriaterület felszabadítása is a programozó feladata (Free).

slide25

Var EgyNap : TDatum;

begin

EgyNap := Tdatum.Create;

EgyNap.Beallit(2003,4,6); { használat }

EgyNap.Free; { felszabadítás }

end;

Az adatmezők és a metódusok mellett az osztálytípusok tulajdonságokat (property) is tartalmazhatnak. A tulajdonság egy olyan név, amely a megadott olvasás és/vagy írás műveleteken keresztül férhet hozzá az objektum adattagjaihoz.

egys ges jel l si m dok az oszt lydiagram
Egységes jelölési módok: az osztálydiagram

Osztály

Adat

Adat: típus

Adat: típus= érték

metódus

metódus(paraméterlista)

metódus: típus

metódus(paraméterlista):típus

Az osztály neve

Adatok

metódusok

Az osztálydiagram tartalmazza az osztály nevét, az objektumok megvalósítására használt adatokat és típusukat, valamint a metódusokat. Az adatok az állapotok belső leírásai, a metódusok műveletek vagy üzenetek.

egys ges jel l si m dok az objektumdiagram
Egységes jelölési módok: az objektumdiagram

Obj: Osztály

adat1 = érték1

adat2 = érték2

adatn = értékn

Az objektum azonosítója és az osztály neve, amelynek példánya

állapot

példányszám

Osztály

Objektum

példányosítás

slide28

Az egyes programok objektumaira jellemző az életciklusuk: „megszületnek”, „élnek”, „meghalnak”.

Az objektum kezdeti állapotát a konstruktor állítja be. Ekkor történik meg az objektum adattagjainak kezdőértékadása és az objektum működéséhez szükséges kezdeti tevékenységek végrehajtása. A nyilvános osztályok konstruktorának is nyilvánosnak kell lennie, hogy az objektumot tartalmazó program hozzáférhessen.

Egyes nyelvekben destruktor is van, melyet az objektum megszűnésekor vagy a programozó, vagy a rendszer meghív és így memóriát szabadít fel.

slide29

C++ példa konstruktorra

classKomplex {

doublere, im;

public:

Komplex() { re=0; im=0;}

Komplex(double a, double b) {re=a, re=b;}

}

…..; Komplex z1; …….. Komplex z2(1,1);

C++-ban egy osztály konstruktorának neve megegyezik az osztály nevével. Egy osztálynak több konstruktora lehet a függvénynév túlterhelés miatt

Az objektumok felszabadítását a destruktor végzi. A destruktor neve az osztálynév elé írt ~(tilde) jellel képezhető.

A statikus objektum megszűnésekor illetve a dinamikus objektum helyének felszabadításakor a destruktor automatikusan meghívódik. Paramétere nincs, mivel nem feltétlenül a programozó hívja meg.

slide30

Object Pascal

type

Tdatum = class

private

ev, ho, nap: integer;

public

constructorCreate(e,h,n: integer); …

end;

constructorTdatum.Create(e,h,n: integer);

Object Pascalban egy osztályhoz több különböző konstruktort hozhatunk létre, ezek neve tetszőleges lehet és akármennyi paraméterük lehet. Deklarálásukkor a constructor kulcsszót kell használni. A TObject osztály (minden osztály őse) konstruktorának neve Create, ezt szokás használni.

Object Pascalban a konstruktort az objektumpéldány használata előtt külön meg kell hívni. Az alapértelmezett destruktor a Destroy, akkor híjuk meg, ha már nincs szükségünk az objektumra.

slide31

Eiffel

classKOMPLEX

creation

ertekadás

feature

valos, kepzetes: REAL

feature

ertekadas(r,i: REAL)is

do

valos := r;

kepzetes:=i

end;

end

Eiffelben a konstruktort a creation záradékkal lehet megadni.

Az alábbi utasítás hatására létrejön a z-hez rendelt objektum, melynek kezdeti értéket is adunk.

z: KOMPLEX;

!!z.ertekadas(1,0);

Eiffelben nincs explicit destruktor. Amikor egy objektumra már nem hivatkozik többé program, egy automatikus szemétgyűjtő eljárás megszünteti az objektumot (garbage collection)

a p ld nyos t s s a self
A példányosítás és a Self

Delphi: Self; Java, C++:this;

A példányosítás során létrejön az objektum és utasítások elvégzésére felszólító üzenetekre vár. A metódusokat az osztályhoz rendeljük és nem másoljuk be minden újonnan létrehozott objektumba: a metódusok az osztály leíró részében szerepelnek csak, az objektumban nem. Az objektumok tudják, hogy melyik osztályhoz tartoznak, és ennek alapján történik a metódusok kiválasztása. Kérdés: ha több objektumot példányosítunk egy osztályból, honnan tudjuk, hogy melyik objektum hívta az adott metódust, azaz a metódusnak melyik objektum adataival kell dolgozni? Erre van egy speciális hivatkozás, amely mindig a metódust meghívó aktuális objektumpéldányra mutat. Ez Delphiben a Self, más nyelvekben this. A Self rámutat arra az objektumra, amellyel a metódusnak dolgoznia kell.

slide33

Delphi példa a Self használatára

procedure TCurveFittingForm.Timer1Timer(Sender: TObject);

begin

Timer1.Enabled:=False; { <-- stop timer }

With StockPrice do

Begin

Delete(0); { <-- remove the first point }

{ Add a new random point }

AddXY( XValues.Last+1,

(YValues.Last/YValues.Multiplier)+(Random(ChartSamplesMax)-(ChartSamplesMax/2)),

'',clTeeColor);

Chart1Zoom(Self); { <-- recalculate Curve !!!! }

end;

Timer1.Enabled:=True; { <-- restart timer }

end;

megjegyz sek a 7 elv r s s az oop kapcsolat r l
Megjegyzések a 7 elvárás és az OOP kapcsolatáról

Egységbezárás.

Számos OOP nyelvben az egységbezárás a korábbi struktúra, ill. rekord adattípusát (struct, record) továbbfejlesztve vezeti be az osztálytípust (class).

Ada95-ben az egységbezárás csak közvetetten valósul meg. Az Ada83 rekord fogalmát bővítették ki, de ezen rekordok csak az osztály attributumait tartalmazzák, a műveleteket nem. Így az egységbezárás csak a tagged rekordtípus (tag=cédula, címke) és a műveletek egy modulba (package) helyezésével valósítható meg.

slide35

Adatrejtés és interfész

  • Az egységbezárás az alábbi szabályok segítségével valósul meg:
    • Az objektum csak olyan üzenetekre reagál, amelyekre megtanították
    • Az ojektumot csak az interfészen keresztül lehet elérni
    • Az objektum interfésze alehető legkisebb legyen.
  • Módszertani követelmény, hogy az adatok csak a metódusokon keresztül legyenek elérhetők. Ha a nyelvek egy része ad is lehetőséget az adatok közvetlen elérésére, ezt inkább mellőzzük.
  • Az interfész definiálása a programozó feladata. Ezt úgy tudja elvégezni, hogy megadja az objektum osztályában a külvilág számára elérhető metódusokat, esetleg az adatok egy részhalmazát is: ezek nyilvánosak (public). A rejtett (private) adatokat és metódusokat csak az adott objektum használhatja.
  • Egy adat nyilvános volta ideális esetben csak lekérdezési lehetőséget jelent, felülírási, megváltoztatási lehetőséget nem így van például az Eiffelben.
el rhet s g a c ban
Elérhetőség a C++ -ban

class A {

int i;

public:

voidset_i (intn) {i=n};

intget_i() {returni;};

};

class A1 {

privateint i;

public:

voidset_i (intn) {i=n};

intget_i() {returni;};

};

class A2 {

public:

voidset_i (intn) {i=n};

intget_i() {returni;};

privateint i;

};

A C++ -ban az osztályok definíciójában a láthatóság osztályszintű, azaz az azonos osztályba tartozó objektumok el tudják érni közvetlenül egymás rejtett adatait is. Osztályok esetén a privateaz alapértelmezés, és a nyilvános és rejtett részek tetszés szerinti sorrendben megadhatók. Ezért a baloldali definíciók egyenértékűek.

adatrejt s object pascalban
Adatrejtés Object Pascalban

Az Object Pascalban private kulcsszóval az objektumok belső használatú részeit jelöljük, de ezek ténylegesen csak az osztályt deklaráló egységen (forrásfájlon) kívül nem láthatóak. Így tehát a módszertani elvárások szerinti adatrejtést csak akkor tudjuk megvalósítani, ha MINDEN OSZTÁLYT KÜLÖN FÁJLBA TESZÜNK.

A szokásos módon public jelöli a mindenki által látható részeket. Azalapértelmezés a publishedláthatóság. A published ugyanolyan láthatóságú, mint a public, a különbség az, hogy futásidejű típusinformáció (RTTI=RunTime Type Information) generálódik minden published típushoz. Így egy applikáció dinamikusan lekérdezheti egy objektummezőit és tulajdonságait, valamint megtalálhatja metódusait. Az RTTI technológia használatos a tulajdonságok kezelésére form fájlok mentésekor és betöltésekor, valamint az eseménykezelő (event handler) metódusok és az események összerendelésekor.

l that s g eiffelben
Láthatóság Eiffelben

Az Eiffel nyelv fejlesztői az ún. szelektív láthatóságot valósították meg. Ez azt jelenti, hogy az osztály minden egyes jellemzőjére (feature) külön megadható, hogy mely osztályok érhessék el. Eiffelben a láthatóság objektum és nem osztály szintű, így ha azt akarjuk, hogy az adott osztály más példányai is elérhessenek egy bizonyos jellemzőt, akkor ezt explicite meg kell adnunk a láthatósági szabályokban. A láthatóságra vonatkozó kívánalmakat úgy adhatjuk meg, hogy a feature kulcsszó után kapcsos zárójelek között felsoroljuk azon osztályoknak a nevét, melyek számára az itt következő jellemzőket láthatóvá kívánjuk tenni. A mindenki számára látható az ANY (ez alapértelmezés, így elhagyható), az adott objektumon kívül seholsem látható a NONE szóval adható meg.

eiffel l that s gi p lda
Eiffel láthatósági példa

classC

feature {ANY}

x : T; -- minden osztály láthatja

feature{C}

y: U; -- a C osztály példányai láthatják

feature{NONE}

z: V; -- csak az adott objektumon belül látható

end-- class C

friend met dusok oszt lyok c ban
Friend metódusok, osztályok C++ -ban

A C++ -ban egy másik osztály metódusainak meg lehet engedni, hogy bizonyos esetekben hozzáférjen az objektum adataihoz, és így ismeretségi kapcsolatokat lehet megvalósítani. Ezen metódusokat barát (friend) metódusoknak nevezzük. Ezek nem az osztály objektumainak küldött üzenetek, hanem külső függvények, így nem érvényes az, hogy a Self segítségével látják az objektumot. Ennek megfelelően az aktuális objektumot is meg kell adni egy további paraméterben.

Az is megengedett, hogy egy osztály barátnak nyilvánítson egy másik osztályt. Ekkor a barát osztály metódusai elérhetik az illető osztály privát adatait.

friend Eljárásnév (par_lista);

friend Osztály.Metódus(par_lista);

friend Osztálynév;

slide41

Az osztályok belső állapotát leíró adatokat osztályadatoknak hívjuk. Ezek az adatok az osztályról tárolnak információkat és így nem feltétlenül változnak az egyes objektumok állapotváltozásaival együtt. Helyük az osztály helyfoglalásakor foglalódik le és az osztály helyének felszabadulásakor szabadul fel. Egyes nyelvekben (C++, Java, C#) ezek az osztályváltozók ún. statikus adatok (static) és az osztály objektumai is tudják használni őket. Egy adott osztályváltozóból mindig pontosan egy létezik és az osztály minden egyes példánya ezen „osztozik”. Például egy osztály esetén egy osztályváltozóban számolhatjuk az ehhez az osztályhoz létrehozott objektumokat.

slide42

classDatum{

intev, ho, nap;

staticDatum alapert_datum; // osztálymetódus

public:

Datum (intee=0, inthh=0,intnn=0);

//…

static voidbeallit_alapert(int,int,int);

};

Datum::Datum(int ee, int hh, int nn){// :: scope access operátor, a globálisra vonatkozik

// ha paraméter nélküli konstruktor hívás történik, akkor az alapert_datum értéket kapja

// az új objektum

ev = ee ? ee : alapert_datum.ev; // ha ee=true vagy nem 0, akkor ee, egyébként …

ho = ho ? ho : alapert_datum.ho;

nap = nap ? nap : alapert_datum.nap;

};

void Datum::beallit_alapert(int e, int h, int n)

{ // a statikus adattag értékének megváltoztatására

Datum::alapert_datum = Datum(e,h,n);

};

Datum Datum::beallit_alapert(2003,3,16); // a statikus adattag definiálása

oszt lymet dus object pascalban
Osztálymetódus Object Pascalban

Az object Pascalban azt, hogy egy műveletet osztálymetódusként akarunk használni, az osztály definíciójában a class kulcsszóval jelezhetjük. B az osztály objektumainak metódusa, míg ObjSzam az A osztálymetódusa.

type

A = class

procedureB;

class functionObjSzam: integer;

end;

implementation

varObjSz: integer=0;

class functionA.ObjSzam:integer;

begin

Result := ObjSz;

end;

Az ObjSzamosztálymetódus törzsében levő ObjSz rejtett változót az osztály összes objektuma és az osztálymetódus(ok) közösen használhatják.

slide44

Az osztálydiagramoknál is szokás feltüntetni, ha egy adat osztályadat, vagy ha egy metódus osztálymetódus, ami az adat- vagy metódusnév elé írt C betű jelez. A + jel a nyilvános, a – jel a rejtett elérést jelenti.

r kl d s
Öröklődés

Az OO megközelítés a valós világ objektumait – tulajdonságaik alapján – osztályokba sorolja. Minden kategóriának számos alkategóriája lehet, és ezen kategóriák alatt további alkategóriák vannak.

Az alosztályok létrehozásakor mindig támaszkodunk annak az osztálynak a tulajdonságaira, amelyiknek az új alosztály része: az alosztály örökli az ősosztály tulajdonságait. Az ősosztály is lehet, hogy valamely más osztály alosztálya, tehát tulajdonságainak egy részét örökölte.

A specializációt úgy valósítjuk meg, hogy az egyes alosztályokba új attribútumokat vezetünk be. Például, ha az Emberek osztályt az Élőlények osztályból származtatjuk, akkor bevezethetjük például az anyanyelv attribútumot, amely csak az Emberek alosztály tagjaira érvényes.

slide46

Lehetőséget kell biztosítani arra is, hogy az egyes alosztályokban bővítsük a műveletek halmazát olyan műveletekkel, amelyek az ősben nincsenek.

Az altípusképzés során megengedjük a változtatást is, azaz hogy az új osztályban egyes műveletek átdefiniálhatók legyenek, implementációjuk, esetleg specifikációjuk is különbözzön az ősosztálybeliétől. Dinamikus összekapcsolás kell, hogy lehetőséget adjon arra, hogy a változó aktuális típusa – futásközben – határozza meg a művelet végrehajtandó implementációját. A műveletek átdefiniálása nem történhet tetszőlegesen (erre még visszatérünk). Ezt a műveletet specifikáció öröklésnek nevezzük.

Egy meglevő osztályt bármikor felhasználhatunk más osztályok definiálására azzal a céllal is, hogy a már meglévő kódot újra fel tudjuk használni. Ez akkor valósul meg, ha a leszármaztatott osztály implementációjában rejtetten használjuk az ősosztályt. Ezt nevezhetjük újrafelhasználó öröklésnek vagy implementációs öröklődésnek.

slide47

Az öröklődés lehet egyszeres vagy többszörös. Egyszeres öröklődésről akkor beszélünk, ha a leszármaztatott osztálynak pontosan egy közvetlen ősosztálya van.

Többszörös öröklődés esetén a leszármaztatottnak legalább két közvetlen ősosztálya van. A leszármaztatott osztály mindig örökli az ősosztály adatait és metódusait. A többszörös öröklődés esete gondot okozhat, ha például két közvetlen ősosztályban is szerepel egy-egy ugyanolyan nevű adat vagy metódus, akkor a leszármaztatott osztályban ez többértelműséghez vezethet (erre visszatérünk).

c p lda r kl d sre
C++ példa öröklődésre

classSikidom{

protected: // származtatott osztályokban látható

int szelesseg, magassag;

public:

voidbeallit_ertekek (inta, intb){

Szelesseg=a; magassag=b;}

};

classTeglalap: publicSikidom{

public:

intterulet(){ return (szelesseg*magassag);}

};

classHaromszog: publicSikidom{

public:

intterulet(){ return (szelesseg*magassag/2);}

};

A Teglalap és a Haromszog osztály is rendelkezik a Sikidom osztályban bevezetett adattagokkal és metódussal. A terulet() metódus új mindkét osztályban, más-más módon definiálva.

slide49

A C++ megengedi a többszörös öröklődést is, ha például az előzőeken túl bevezetjük az Egyenlooldalu osztályt is, akkor a Negyzet osztály lehet ennek és a Teglalap osztálynak is a leszármazottja.

classEgyenlooldalu{

public:

bool e;

};

classNegyzet: publicTeglalap, public Egyenlooldalu{

Negyzet(){ e = true;}

};

r kl d s az object pascalban
Öröklődés az Object Pascalban

type Tallat = class

public

function eszik: string;

private fajta: string;

end;

TKutya = class(TAllat)

public

function ugat: string;

end;

varKutya1 : TKutya;

begin

{….} writeln(Kutya1.eszik);

{….} writeln(Kutya1.ugat);

end.

Az Object Pascal az egyszeres öröklődést támogatja, interfészek segítik a többszörös öröklődést (ld. később).

A TAllat leszármazottja a TKutya, itt vezetjük be a kutyákra jellemző ugat függvényt.

r kl d s az eiffelben
Öröklődés az Eiffelben

Eiffelben az öröklődési kapcsolatok az osztály definíciójában az inherit kulcsszó után adhatók meg. A leszármazott az ősének összes adattagját és metódusát elérheti, és adott esetben módosíthatja az öröklődés során.

Az öröklődési záradékban az inherit kulcsszó után fel kell sorolni azoknak az ősosztályoknak a nevét, amelyektől örökölni szeretnénk,és az egyes ősök redefine záradékaiban kell megadjuk azokat a jellemzőket, amelyeket módosítani szeretnénk az öröklődés során.

Azok a jellemzők, amelyeket nem említünk meg a redefine záradékban, természetesen változatlanul öröklődnek tovább. A nyelv a többszörös öröklődést lehetővé teszi (ld. később).

slide52

class SOKSZOG inherit ALAKZAT

feature kiiris do

io.putstring(”SOKSZÖG VAGYOK”)

end;

end

class NEGYZET inherit SOKSZOG

redefine kir

end

feature kiiris do

io.putstring(”NÉGYZET VAGYOK”)

end;

end

SOKSZOG őse alakzat, NEGYZET őse SOKSZOG, kiir-t újradefiniáljuk a NEGYZET-ben.

adatrejt s s r kl d s kapcsolata
Adatrejtés és öröklődés kapcsolata

Object Pascalban a privát rejtésre vonatkozó megállapítás csak a különböző fordítási egységben bevezetett osztályok esetén igaz.

slide54

Tegyük fel, hogy az A osztály tartalmaz egy nyilvános m metódust és egy privát i adatot. Feltételezzük, hogy az m metódus használja az i adatot. Ha a B osztály az A-ból öröklődik, akkor természetesen örökli az m metódust, és ez minden további nélkül használni tudja az i adatot, habár az nem látható B-ben, és így egyetlen más új B-beli metódus sem tudja közvetlenül használni. A rejtettként deklarált adatok és metódusok is átöröklődnek, csak ezek nem lesznek láthatók a leszármazott osztályban.

A

- i

+ m

B

Számos programozási nyelv megengedi azt is hogy egyszerű újradeklarálással a leszármaztatott osztály megváltoztassa az adatok, metódusok adatrejtési módját. Például, ha a leszármaztatottban nyilvánosként vezettünk be egy, az ősben már eleve védettként bevezetett metódust, akkor ez a művelet a továbbiakban nyilvános lesz.

slide55

Tegyük fel, hogy a Kör osztály az Alakzat osztály örököseként jött létre. Ekkor a Kör objektumaira igaz, hogy azok Alakzat típusúak is. De ha egy Kör típusúként deklarált kiskör objektumot tekinthetünk Alakzat típusúként is, akkor értékül is adhatjuk egy alak nevű, Alakzat típusú objektumnak, azaz megengedett az alak:=kiskör értékadás. Ugyanakkor, mivel fordítva nem igaz az állítás, hiszen egy Alakzat-beli objektum nem feltétlenül esik a Kör által leírt altípusba, ezért a kiskör:= alak értékadás nem megengedett. Hogyan oldjuk fel, hogy az alak:=kiskör értékadás ne okozzon típuskeveredést?

slide56

Vezessük be a statikus és dinamikus típus fogalmát. Egy változó statikus típusa az az osztály, mellyel a deklaráció során összekapcsoltuk. A változó dinamikus típusa pedig a statikus típus vagy annak egy leszármazottja lehet. Az előző példában az alak statikus típusa az Alakzat osztály, míg az alak:=kiskör értékadás után dinamikus típusa a Kör osztály.

Azt a lehetőséget, hogy egy változó a program futása során több osztály objektumára is hivatkozhat, nevezzük a változók polimorfizmusának (többalakúságának).

Az öröklődés során megengedjük, hogy a leszármazottaknál az egyes műveletek implementációja és/vagy specifikációja különbözzön az ősosztályban bevezetett művelettől. Például, ha az Alakzat-nak van egy Kirajzol művelete,és ezt a Kör osztályban felülbíráltuk, akkor az alak:=kiskör értékadás után azt várjuk, hogy az alak-ra alkalmazott Kirajzol művelet a Kör osztályban meghatározott műveletet végezze el.

A dinamikus összekapcsolás – amely futásidejű esemény – ad lehetőséget arra, hogy a változó dinamikus típusa határozza meg a végrehajtandó implementációját. Ezt virtuális műveletnek nevezik.

statikus s dinamikus tdefini l s
Statikus és dinamikus átdefiniálás

Több programozási nyelvben (például Object Pascal vagy C++) az objektumok metódusai alapértelmezésben statikus kötésűek. Például az alak.Kirajzol esetén az alak statikus típusa alapján az Alakzat osztályban, míg a kiskör statikus típusa alapján a Kör osztályban definiált Kirajzol művelet meghívása szerepel a végrehajtandó kódban.

Dinamikus kötés esetén a meghívott metódus címe ténylegesen csak futási időben derül ki, hiszen ha valamely osztály változójának a leszármazott osztályok objektumai is értékül adhatók, akkor csak futás közben lehet eldönteni, hogy az adott metódus melyik osztálybeli megvalósítását kell meghívni. Kifejezetten objektumorientáltnak tervezett nyelveknél (Smalltalk, Java, Eiffel) ez utóbbi az alapértelmezés.

Egyes nyelveknél lehet virtuális metódusokat deklarálni, és a virtuális metódusok hívásai lesznek dinamikus kötésűek. Egy új osztály deklarálásakor virtuális metódusai bekerülnek az osztály ún. Virtuális Metódus Táblájába (VMT). Virtuális metódus hívása esetén a program a megfelelő VMT-ből olvassa ki, hogy melyik metódust kell meghívnia.

slide58

#include <iostream.h>

#include <conio.h>

class Teglalap{

protected: int szelesseg, magassag;

public: Teglalap(int a, int b){szelesseg=a; magassag=b;};

virtual int f(){ return (0); }

};

class Szines_Teglalap: public Teglalap{

int szin;

public: Szines_Teglalap(int a, int b, int c): Teglalap(a,b),

szin(c) {};

virtual int f() { return(szin); }

};

void main(){ clrscr();

Teglalap a(2,3); Szines_Teglalap t(3,4,5);

a = t; cout << a.f()<<"..."; // csonkítás

Teglalap* a1 = &a; Teglalap* a2 = &t;

cout<<a1->f()<<"---"; cout<<a2->f();

}

0…0---5

lesz az output.

Itt a poliformizmus látszólagos, mert az f() függvényt statikusan köti az objektumhoz.

Itt valódi a poliformizmus és megvalósul a dinamikus kötés.

C++

slide59

Az Object Pascal változói objektumok referenciái, a polimorfizmus azt jelenti, hogy az ősosztálybeli referencia aktuálisan valamelyik leszármazott osztály objektumára is hivatkozhat. A metódusok alapértelmezésben statikusak. Dinamikus metódust a virtual kulcsszóval kell bevezetni:

procedure f; virtual

Ha ezt a leszármazottban szeretnénk felüldefiniálni, akkor az override kulcsszóval tehetjük meg:

procedure f; override

Lehetséges a metódusnevek túlterhelése is, ehhez az overload kulcsszót használjuk:

procedure f(a: string); overload

Túlterhelésnél – azonos paraméterezés esetén – az újonnan bevezetett metódus eltakarja a régit.

az soszt ly met dusainak megh v sa
Az ősosztály metódusainak meghívása

Delphi

Szükség lehet arra, hogy meghívjuk az ősosztály vagy az ősosztályok metódusait, vagy akár arra is, hogy a gyermekosztályban egy örökölt metódust úgy bővítsünk ki, hogy felhasználjuk a már meglevő, az ősosztályban megírt metódust. Object Pascalban az inherited kulcsszóval hivatkozhatunk egy metóduson, vagy akár egy konstruktoron belül is az ősosztály ugyanilyen nevű metódusára.

typeTSzulo = class…

proceduref(…);virtual;…

end;

typeTGyerek = class (TSzulo)

proceduref(…);override;…

end;

procedureTGyerek.f(…);

begin

inheritedf(…);…

end;

Itt a TSzulo f műveletét hívjuk!

t bbsz r s r kl d s
Többszörös öröklődés

Többszörös öröklődésről beszélünk, ha egy osztálynak egynél több közvetlen őse van. Ez azt jelenti, hogy az adott osztály két (vagy több) osztály alosztályának is tekinthető. Például a VALLALATI_REPULOGEP osztály mind a REPULOGEP, mind a VALLALAT osztály alosztályaként kezelhető.

slide62

#include <iostream.h>

#include <conio.h>

class A{

public: virtual void f(){ cout << "f az A-ban\n"; }

};

class B{

public: virtual void g() = 0;

};

class C : public A, public B {

public:

void f() {cout << "f a C-ben\n";};

void g() {cout << "g a C-ben\n";};

};

int main(){ clrscr();

A* a1; B* b1; C c;

a1 = &c; b1 = &c;

a1->f(); b1->g();

return 0;

// cout<<a1->f()<<"---";

// cout<<a2->f();

}

C++

C++

Output:

f a C-ben

g a C-ben

f specifikációsan öröklődik A-tól,

g implementációsan öröklődik B-től

Az ősökön keresztül csak a tőlük örökölt metódusok érhetők el,

a1->g(); értelmetlen.

slide63

C++

#include <iostream.h>

#include <conio.h>

class A{

public: virtual void f(){ cout << "f az A-ban\n"; }

};

class B{

public: virtual void f(){cout<<"f a B-ben\n";};

};

class C : public A, public B {

public:

virtual void f() {cout << "f a C-ben\n";};

};

int main(){

clrscr();

A* a1; B* b1; C c;

a1 = &c; b1 = &c;

a1->f(); b1->f(); c.f();

return 0;

}

Output:

f a C-ben

f a C-ben

f a C-ben

a rombusz r kl d s probl m ja
A rombusz-öröklődés problémája

A többszörös öröklődés egy különleges lehetősége az ismételt öröklődés, amikor egy leszármazott valamelyik ősosztályát az öröklődési gráfban többféle úton is eléri, többször örökli ugyanazokat az attribútumokat vagy metódusokat. Ha ugyanis egy A ősosztályban létezik legalább egy adat (attr_a) vagy egy metódus (f), az A osztály minden leszármazottja örökli ezeket. Tegyük fel, hogy az A osztálynak van két leszármazottja, B és C, ekkor ezeknek is lesz egy attr_a attribútuma és f metódusa, sőt át is definiálhatják az öröklött f metódust. Ha létrehozunk egy új D leszármazottat, amely többszörös öröklődést használva B-ből és C-ből öröklődik, akkor hány példányban jelenjen meg D-ben az örökölt adat vagy metódus? A válasz nyelvi megoldásonként különbözik.

slide65

C++ -ban az az alapértelmezés, hogy a leszármazottban minden adattag annyiszor jelenik meg, ahányszor a közös őstől örököltük, s az osztálynévvel minősítve különböztetjük meg az azonos nevű adattagokat.

Lehetnek olyan esetek, amikor nincs értelme a közös őstől örökölt tagokat többszörözni. Például, ha a Szemely osztályt jellemezzük a Neve, Szuletesi_hely adatokkal, és származtatjuk többszörös öröklődéssel a Hallgatoi_gyakvez osztályt, aki Tanar és Diak egyszerre, akkor nincs értelme, hogy a Neve, Szuletesi_hely adatokat egynél többször tároljuk. A Tanar és a Diak tekinthetik ősüket virtuálisnak, és ekkor a Szemely osztálytól örökölt adatok csak egyszer jelennek meg a Hallgatoi_gyakvez osztályban. Ha a Szemelyben egyszer és többször tárolandó adattagok is vannak, a vegyes kezelés nem oldható meg.

Eiffelben igen. Az alapértelmezés szerint – ellentétben a C++-szal – a közös őstől származott jellemzők csak egyszer jelennek meg, a Hallgatoi_gyakvez viszont átnevezheti valamelyiket és ezáltal többszörözheti.

javasolt ellen rz k rd sek
Javasolt ellenőrző kérdések
  • Milyen szabályok és ajánlások fogalmazhatók meg az egységbezárásnál?
  • Mire való a self és a this?
  • Milyen probléma megoldásakor érdemes friend osztályt használni?
  • Mely mindennapi életből vett feladattal szemléltetné az öröklődést?
  • Ismertesse példán keresztül a dinamikus kötést!
  • Ismertesse a polimorfizmus lehetőségeit C++-ban!
  • Ismertesse a különböző tanult nyelvekben a konstruktor és destruktor lehetőségeket!
  • Mi a rombusz öröklődés problémája?
  • Ismertesse a C++ többszörös öröklődésre vonatkozó megoldását példán keresztül!
  • Jellemezze a C++ öröklési módjait.
  • Jellemezze az Object Pascal adatrejtését.
  • Sorolja fel a programnyelvekkel szemben támasztott 7 elvárást.
  • Mire való C++-ban a make?
  • Mit jelent az azonosító túlterhelése illetve felüldefiniálása?
  • Mi az előnye a típusspecifikáció és a megvalósítás szétválasztásának?
  • Adjon példát specifikációs és implementációs öröklődésre!