Programozás módszertan Öröklődés Pere László (pipas@linux.pte.hu) PÉCSI TUDOMÁNYEGYETEM TERMÉSZETTUDOMÁNYI KAR INFORMATIKA ÉS ÁLTALÁNOS TECHNIKA TANSZÉK MAGYAR TUDOMÁNYOS AKADÉMIA SZÁMÍTÁSTECHNIKAI ÉS AUTOMATIZÁLÁSI KUTATÓINTÉZET ELEARNING OSZTÁLY Programozás módszertan p.1/46
Bevezetés Programozás módszertan p.2/46
Általános vs. speciális Az absztrakció folyamatára nem csak az absztrakt tárgyak (pl. asztal) létrehozása, hanem a köztük megfigyelhető viszonyok feltérképezése is jellemző (pl. tárgy, bútor, asztal, íróasztal és tárgy, jármű, személygépkocsi). Az absztrakció során egy hierarchiát hozunk létre az absztrakt tárgyakból. A hierarchikus rendszerben az általánostól a speciálisig haladva az egyes absztrakt tárgyak rendelkeznek az előző tárgy összes tulajdonságaival, azokat bővítik, finomítják, specializálják. Programozás módszertan p.3/46
Öröklődés Az objektumorientált módszertan az absztrakt tárgyak modellezésére az osztályokat használja. Az absztrakció során az absztrakt tárgyakból létrehozott hierarchiát az objektumorientált programozás során az osztályok közt létrehozott hierarchiával modellezhetjük. Az osztályok közt létrehozott hierarchiában az általánostól a speciálisig haladunk, a rákövetkező osztály örökli az előző osztály adattagjait és metódusait. Programozás módszertan p.4/46
Ismétlés Objektum alapú nyelvek: támogatják az objektumok létrehozását, de nem ismerik az osztály fogalmát. Osztály alapú nyelvek: támogatják az osztályok létrehozását, de a köztük lévő viszonyokat nem ábrázolják. Objektumorientált nyelvek: támogatják az osztályok közti viszonyok ábrázolását az öröklődés eszközével. Csak azokat a nyelveket nevezhetjük objektumorientált nyelveknek, amelyek az osztályok közti viszonyokat az öröklődés eszközével képesek kezelni! Programozás módszertan p.5/46
Elnevezések Az osztály létrehozásakor meghatározhatjuk, hogy mely létező osztály (vagy osztályok) tulajdonságait örökölje az új osztály. Az öröklő osztályt örökösnek, az öröklött tulajdonságokat hordozó osztályt szülőnek vagy ősnek nevezzük. A szülő mindazon osztályok ősszülője, amelyeknek az örökös a szülője vagy ősszülője. Az osztály az összes ősszülőjének leszármazottja. Programozás módszertan p.6/46
Polimorfizmus Polimorfizmus (többalakúság): az objektumorientált programozási nyelvek típusrendszere úgy van kialakítva, hogy mindazon helyeken, ahol a szülő vagy az ősszülő szerepelhet, szerepelhet az örökös is. Példa: Ha egy függvény képes az állat osztályba tartozó objektumot kezelni, képes a leszármazottként létrehozott emlős és méhlepényes emlős osztály objektumait is kezelni. A polimorfizmus az ellenkező irányban nem érvényes! Programozás módszertan p.7/46
Specializáció Az öröklődés során az általánostól a speciális irányába haladunk. Ezt a legtöbbször úgy tesszük, hogy a szülő osztályt új attribútumokkal (adattag, metódus) bővítjük. Példa: Az ember osztályt az alkalmazott osztályban a fizetéssel és a munkakörrel, az üzletfél osztályban az eddigi vásárlások összértékével bővítjük. Az attribútumok bővítése a típusértékhalmaz szűkítésével jár. Programozás módszertan p.8/46
Specializáció A specializációt támogatandó általában lehetőségünk van arra is, hogy az ősosztály valamely attribútumát (adattagját vagy metódusát) megváltoztassuk, újradefiniáljuk. Példa: A síkidom osztályban a kirajzolást végző metódus általános eszköz, a leszármazott téglalap osztály kirajzolását végző metódusa azonban már lehet egy hatékonyabb algoritmust használó speciális eszköz. Programozás módszertan p.9/46
Dinamikus összekapcsolás A dinamikus összekapcsolás eszköze ad lehetőséget arra, hogy az objektumot aktuális típusa szerint valamelyik ősszülő vagy a saját attribútumaival kezeljük. Példa: Ha a téglalap osztály objektumát a síkidom osztály objektumaként használjuk (polimorfizmus), akkor a téglalap osztály objektumát a síkidom osztály attribútumaival jellemezzük és kezeljük vagy a téglalap osztály attribútumaival. Programozás módszertan p.10/46
Többszörös öröklődés Bizonyos objektumorientált programozási nyelvek megengedik, hogy az osztálynak egyszerre több szülője, közvetlen ősosztálya legyen. Ilyen esetben az osztály minden szülőjének attribútumait örökli. A többszörös öröklődés kezelése problémákat vet fel, ha például ugyanazon a néven több szülőtől örököl az osztály attribútumot. A többszörös öröklődés igen hatékony, nagy kifejezőerejű eszköz lehet, használata azonban nem egyszerű! Programozás módszertan p.11/46
Öröklődés a különféle nyelvekben Programozás módszertan p.12/46
SIMULA 67 A SIMULA 67 volt az első programozási nyelv, amely támogatta az öröklődést, azaz a SIMULA 67 volt az első objektumorientált nyelv. A nyelv nem támogatja a többszörös öröklődést, minden osztálynak csak egy közvetlen ősosztálya lehet! Programozás módszertan p.13/46
Smalltalk A Smalltalk támogatja az öröklődést, így a Smalltalk is objektumorientált nyelvnek tekinthető. Programozás módszertan p.14/46
C++ A C++ nyelv támogatja az öröklődést, így objektumorientált nyelvnek tekinthető. A C++ nyelvben megengedett a többszörös öröklődés, egy osztálynak több közvetlen ősosztálya is lehet. Programozás módszertan p.15/46
Object Pascal Az Object Pascal támogatja az öröklődést az osztályok közt. A nyelv csak olyan osztályok közt teszi lehetővé a többszörös öröklődést, amelyek: nem rendelkeznek egyetlen adattaggal sem a bennük definiált metódusoknak nincsen törzsük. Az ilyen osztályokat interfészeknek hívjuk. Programozás módszertan p.16/46
Eiffel Az Eiffel programozási nyelv támogatja az öröklődést és a többszörös öröklődést is. A nyelvet használva a leszármazott osztályban csak azokat az attribútumokat definiálhatjuk újra, amelyeket az ősökben újradefiniálhatóként hoztunk létre. Programozás módszertan p.17/46
Java A Java nyelv támogatja az öröklődést, de a többszörös öröklődést csak az Object Pascal nyelvnél megfigyelhető esetekben teszi lehetővé. A Java nyelvben az osztály létrehozásakor megtilthatjuk, hogy az osztálynak örököse legyen. Programozás módszertan p.18/46
C# A C# nyelvben az öröklődés a szerzők szerint a C++ nyelvhez hasonlóan történik, valójában azonban jobban hasonlít a Java öröklési rendszerére. A C# a többszörös öröklődést csak a Java nyelvhez hasonló különleges esetekben teszi lehetővé. A C# nyelvben az osztály létrehozásakor megtilthatjuk a leszármazott létrehozását. Programozás módszertan p.19/46
Öröklési módok, adatrejtés Programozás módszertan p.20/46
Adatrejtés és öröklődés A public és a private adatrejtési módokon kívül sok nyelvben létezik a protected (védett) adatrejtési mód is. A protected adatrejtéssel létrehozott attibútumok a leszármazottban public-ként, másutt pedig private-ként viselkedik. kívül objektum leszármazott public igen igen igen protected nem igen igen private nem igen nem Figyeljük meg, hogy a leszármazott a private attribútumokat rejtett módon örökli! Programozás módszertan p.21/46
Öröklési módok Néhány programozási nyelv megengedi, hogy az előbbiekben bemutatott adatrejtési rendszert felülbíráljuk, azaz megváltoztassuk a öröklés hatását az adatrejtésre. Az ilyen nyelvekben felülbírálhatjuk az ős adatrejtési rendszerét, ezzel például megoldva a többszörös öröklődés problémáit. A C++ nyelv például három öröklési módot képes kezelni. Programozás módszertan p.22/46
Öröklési módok A C++ nyelvben három öröklési mód létezik: public Megtartja az ősök láthatósági szintjeit. private Minden örökölt attribútum rejtetté válik. protected Minden örökölt attribútum védett lesz. Bármelyik öröklési módot válasszuk, az ősben rejtettként definiált attribútumok a leszármazottban közvetlenül nem lesznek elérhetők. Az alapértelmezett öröklési mód a private. Programozás módszertan p.23/46
C++ öröklődés ős öröklődés leszármazott private public közvetlenül nem elérhető protected public protected public public public private private közvetlenül nem elérhető protected private private public private private private protected közvetlenül nem elérhető protected protected protected public protected protected Programozás módszertan p.24/46
Polimorfizmus és dinamikus kötés Programozás módszertan p.25/46
Helyettesíthetőség A leszármaztatott osztály objektumai bármilyen körülmények között helyettesíthetik az ősosztály objektumait. A helyettesíthetőséget többalakúságnak (polimorfizmus) is nevezzük. Meg kell jegyeznünk, hogy a polimorfizmus csak egy szemantikai eszköz, amelyet ki kell tudnunk használni. Az osztályokat úgy kell létrehoznunk, hogy a leszármaztatott osztály objektumai valóban helyettesíthessék az ősosztály objektumait. Programozás módszertan p.26/46
Típusellenőrzés Fontos kérdés, hogy az adott nyelv hogyan kezeli a többalakúságot, milyen módon képes a típusrendszer ellenőrizni a típusokat. Probléma: Legyen a Tárgy osztály leszármazottja a Jármű, valamint legyenek a tárgy és a jármű változók a megfelelő típusú objektumok. Akkor nyilván megengedett a tárgy = jármű értékadás, de milyen típusa lesz ezek után a tárgy változónak? Programozás módszertan p.27/46
Típusellenőrzés nélkül A dilemma egyik megoldása lehet, hogy kikapcsoljuk a típusellenőrzést és tetszőleges értékadást megengedünk (pl. Smalltalk). Ilyen esetben a típusrendszer hibakereső szolgáltatásairól lemondunk, a programozónak kell a típusok karbantartásáról gondoskodnia. Ez nyilván egyszerű, de szerencsétlen megoldás. Programozás módszertan p.28/46
Statikus/dinamikus típus Másik megoldást jelenthet a statikus és dinamikus típus megkülönböztetése. A statikus típus a változó azon típusa, amelyet a deklarációban megadtunk. A statikus típus fordítási időben ismert, ellenőrizhető. A dinamikus típus a változó által az adott pillanatban hordozott adat típusa. A dinamikus típus megállapítására és ellenőrzésére csak futási időben van mód. Programozás módszertan p.29/46
Dinamikus kötés Az öröklődés során lehetővé tesszük, hogy az egyes leszármazottnál a metódusok implementációja és/vagy specifikációja különbözzön. Kérdés, hogy a polimorfizmus kihasználása esetén melyik metódust használjuk: az ős, vagy a leszármazott metódusát használjuk az ősnek megfelelő statikus és a leszármazottnak megfelelő dinamikus típusú változó esetében? A dinamikus összekapcsolás lehetővé teszi, hogy a változó dinamikus típusa alapján meghatározott implementációt használjuk. Programozás módszertan p.30/46
Dinamikus kötés A dinamikus kötés futási időben történik, vagyis futási időben derül ki pontosan melyik metódus hajtódjon végre. A legtöbb programozási nyelvben a dinamikusan kapcsolódó alprogramot virtuális alprogramnak (virtuális művelet, virtuális függvény) nevezzük. Programozás módszertan p.31/46
Statikus/dinamikus kötés Számos programozási nyelv a statikus kötést (a meghívandó metódusok fordítási időben ismertek, statikus típustól függenek) és a dinamikus kötést is támogatják. Az ilyen nyelvek esetében a programozó határozhatja meg, hogy statikus vagy dinamikus kötést használ az adott esetben. Általában azoknál a programozási nyelveknél, amelyeket eredetileg is objektumorientált nyelvként terveztek, a dinamikus kötés az alapértelmezett. Programozás módszertan p.32/46
C++ A C++ nyelv esetében a dinamikus kötésre a virtual kulcsszó segítségével van módunk. A C++ nyelvben tehát a statikus kötés az alapértelmezett. Az ősosztálybeli objektumok értékül felvehetik a leszármazott objektumokat, de ha nem pointereket vagy referenciákat használunk, a virtuális metódusok is statikus kötéssel kapcsolódnak. Programozás módszertan p.33/46
C++ A leszármazott a metódusok csak korlátozott formában definiálhatja újra: A metódusok paraméterlistája meg kell, hogy egyezzen az ősben és a leszármazottban. A leszármazott metódusának visszatérési értéke az ős metódusának visszatérési értékével megegyező vagy az ős metódus visszatérési értékének leszármazottja kell, hogy legyen. Ha ezeket a szabályokat nem tartjuk be, a leszármazott metódusa az ős metódusának túlterhelése lesz, nem pedig virtuális függvény. Programozás módszertan p.34/46
Object Pascal Az Object Pascalban a metódusok referenciáira érvényes a polimorfizmus. A nyelvben a statikus kötés az alapértelmezett, dinamikus kötést a virtual kulcsszóval valósíthatunk meg. Programozás módszertan p.35/46
Java A Java nyelvben minden változó objektumok referenciája, így az objektumorientált programozás támogatása sokkal jellemzőbb az előző két nyelvnél. A polimorfizmus és a dinamikus kötés az alapértelmezett viselkedés. Programozás módszertan p.36/46
C# A C# programozási nyelvben az objektumokat referenciákon keresztül használjuk. A nyelv támogatja a statikus és a dinamikus összekapcsolást is, a dinamikus összekapcsoláshoz a virtual kulcsszó használata szükséges. Programozás módszertan p.37/46
Az ős metódusai A programozás során szükségünk lehet arra, hogy az ősosztály metódusait hívjuk. A leszármaztatott osztály metódusaiban például építhetünk az ősosztály hasonló szerepet betöltő metódusaira tovább finomítva, specializálva azok eredményeit. Hogyan készítsünk szenes bablevest? Készítsünk egy bablevest és helyezzünk el benne némi brikettet... Programozás módszertan p.38/46
Az ős metódusai Azoknál a programozási nyelveknél, ahol a leszármazottnak csak egyetlen őse lehet (egyszeres öröklődés) általában elegendő egy kulcsszóval jelezni, hogy az ős metódusát szeretnénk meghívni. A többszörös öröklődést is támogató nyelvek esetében általában valamelyik ős nevével minősítjük a metódushívást. Programozás módszertan p.39/46
Új metódusok A leszármazott osztályban a specializáció során új metódusokat vezethetünk be. Kérdés, hogy a őstípusnak megfelelő statikus típusú, a leszármaztatottnak megfelelő dinamikus típusú objektum esetén megengedhetjük-e azoknak a metódusoknak a hívását, amelyek az ősben nem, csak a leszármazottban vannak jelen? Programozás módszertan p.40/46
Új metódusok A programozási nyelvek jelentős hányada (a C++ is), a hívható metódusok listáját a változó statikus típusa alapján határozza meg, vagyis nem hívhatók olyan metódusok, amelyek csak a dinamikus típusban meghatározott osztályban léteznek. Ez egyszerűen biztonságosabb így. Programozás módszertan p.41/46
Absztrakt osztályok Programozás módszertan p.42/46
Absztrakt osztályok A polimorfizmus és dinamikus kötés segítségével lehetőségünk nyílik arra, hogy olyan ősosztályokat hozzunk létre, amelyekben még nem döntünk a konkrét megvalósításról. Az ilyen osztályokat absztrakt osztályoknak nevezzük. Az absztrakt osztályok absztrakt metódusokat tartalmaznak, amelyeknek nincsen törzsük, csak a leszármazottakban implementáljuk őket. Programozás módszertan p.43/46
Absztrakt osztályok Az absztrakt osztályokból általában nem készíthetünk objektumokat, azokat csak a leszármazottaikon keresztül használhatók. Az absztrakt osztályoknak általában lehetnek absztrakt leszármazottaik is, így az implementációt fokozatosan végezhetjük el. Absztrakt osztályokat általában nagyobb szoftverprojekt, mély öröklési hierarchia esetén használunk. Programozás módszertan p.44/46
Ajánlott irodalom Programozás módszertan p.45/46
Ajánlott irodalom [2] NYÉKYNÉ GAIZLER JUDIT (szerk.): Programozási nyelvek, Kiskapu (2003), ISBN: 963 9301 46 9. Programozás módszertan p.46/46