Bevezetés a Programozásba II 8. előadás. Polimorfizmus Giachetta Roberto

Hasonló dokumentumok
Alkalmazott modul: Programozás 11. előadás. Objektumorientált programozás: öröklődés

Objektumelvű alkalmazások fejlesztése 6. gyakorlat. Öröklődés, polimorfizmus. Öröklődés Kódismétlődés objektum-orientált szerkezetben

Szoftvertechnológia 4. előadás. Objektumorientált tervezés: általánosítás. Giachetta Roberto. Eötvös Loránd Tudományegyetem Informatikai Kar

Informatikai Kar. 4. fejezet. Giachetta Roberto

Alkalmazott Modul III 6. előadás. Objektumorientált programozás: öröklődés és polimorfizmus

Java programozási nyelv 5. rész Osztályok III.

Bevezetés a Programozásba II 5. előadás. Objektumorientált programozás és tervezés

Objektumorientált programozás C# nyelven

Programozás II gyakorlat. 6. Polimorfizmus

Öröklés és Polimorfizmus

Alkalmazott modul: Programozás 10. előadás. Objektumorientált programozás: tervezés és megvalósítás

OOP: Java 8.Gy: Abstract osztályok, interfészek

Java programozási nyelv 4. rész Osztályok II.

Programozás módszertan p.1/46

Bevezetés a Programozásba II 2. előadás. Adattípusok megvalósítása egységbe zárással. Adattípusok megvalósítása egységbe zárással

Programozás II. 3. gyakorlat Objektum Orientáltság C++-ban

JAVA PROGRAMOZÁS 2.ELŐADÁS

Programozás II. 2. gyakorlat Áttérés C-ről C++-ra

OAF Gregorics Tibor: Minta dokumentáció a 3. házi feladathoz 1.

C++ programozási nyelv

Bevezetés a Programozásba II 3. előadás. Biztonságos adattípusok megvalósítása

Bevezetés a Programozásba II 3. előadás. Biztonságos adattípusok megvalósítása. Biztonságos adattípusok megvalósítása

Dr. Pál László, Sapientia EMTE, Csíkszereda WEB PROGRAMOZÁS 2.ELŐADÁS. Objektumorientált programozás

és az instanceof operátor

Java VIII. Az interfacei. és az instanceof operátor. Az interfészről általában. Interfészek JAVA-ban. Krizsán Zoltán

Virtuális függvények (late binding)

Számítástechnika II. BMEKOKAA Előadás. Dr. Bécsi Tamás

Már megismert fogalmak áttekintése

3. Osztályok II. Programozás II

Java VII. Polimorfizmus a Java nyelvben

Pelda öröklődésre: import java.io.*; import java.text.*; import java.util.*; import extra.*;

Java VII. Polimorfizmus a Java nyelvben

Alkalmazott Modul III 6. gyakorlat. Objektumorientált programozás: öröklődés és polimorfizmus

Visual C++ osztály készítése, adattagok, és metódusok, láthatóság, konstruktor, destruktor. Objektum létrehozása, használata, öröklés.

Informatikai Kar. 3. fejezet. alapismeretek. Giachetta Roberto

Bevezetés a programozásba előadás: Öröklődés

Interfészek. PPT 2007/2008 tavasz.

Bevezetés a Python programozási nyelvbe

Programozási nyelvek Java

Osztályok. 4. gyakorlat

OOP. Alapelvek Elek Tibor

Széchenyi István Egyetem. Programozás III. Varjasi Norbert

ISA szimulátor objektum-orientált modell (C++)

Objektumorientált programozás C# nyelven

Programozási technológia

Java VI. Miskolci Egyetem Általános Informatikai Tanszék. Utolsó módosítás: Ficsor Lajos. Java VI.: Öröklődés JAVA6 / 1

Programozási alapismeretek 4.

Programozási nyelvek Java

Bevezetés a Programozásba II 10. előadás. Dinamikus memóriakezelés

Számítástechnika II. BMEKOKAA Előadás. Dr. Bécsi Tamás

Számítógép és programozás 2

Helyes-e az alábbi kódrészlet? int i = 1; i = i * 3 + 1; int j; j = i + 1; Nem. Igen. Hányféleképpen lehet Javaban megjegyzést írni?

Bevezetés a Programozásba II 11. előadás. Adatszerkezetek megvalósítása. Adatszerkezetek megvalósítása Adatszerkezetek

Globális operátor overloading

Szoftvertechnológia 3. előadás. Objektumorientált tervezés: alapismeretek. Giachetta Roberto. Eötvös Loránd Tudományegyetem Informatikai Kar

Programozás I. 5. gyakorlat. Szegedi Tudományegyetem Természettudományi és Informatikai Kar

C++ programozási nyelv

Bevezetés a programozásba I 10. gyakorlat. C++: alprogramok deklarációja és paraméterátadása

Bevezetés, a C++ osztályok. Pere László

Statikus adattagok. Statikus adattag inicializálása. Speciális adattagok és tagfüggvények. Általános Informatikai Tanszék

Programozás II gyakorlat. 7. Példák a polimorfizmus alkalmazásaira

A szemantikus elemzés helye. A szemantikus elemzés feladatai. A szemantikus elemzés feladatai. Deklarációk és láthatósági szabályok

Bevezetés a Programozásba II 4. előadás. Adattípusok hordozhatósága

Elemi Alkalmazások Fejlesztése II.

Bevezetés a programozásba Előadás: Objektumszintű és osztályszintű elemek, hibakezelés

Alkalmazott modul: Programozás 4. előadás. Procedurális programozás: iteratív és rekurzív alprogramok. Alprogramok. Alprogramok.

Programozási nyelvek II. JAVA EA+GY 1. gyakolat

Programozás II gyakorlat. 8. Operátor túlterhelés

Bevezetés a programozásba Előadás: A const

Abstract osztályok és interface-ek. 7-dik gyakorlat

Kivételkezelés, beágyazott osztályok. Nyolcadik gyakorlat

Programozás. C++ osztályok. Fodor Attila. Pannon Egyetem Műszaki Informatikai Kar Villamosmérnöki és Információs Rendszerek Tanszék

Objektumok inicializálása

Programozás II. 4. Dr. Iványi Péter

117. AA Megoldó Alfréd AA 117.

1. Template (sablon) 1.1. Függvénysablon Függvénysablon példányosítás Osztálysablon

Osztály és objektum fogalma

BME MOGI Gépészeti informatika 8.

1. Alapok. Programozás II

Alkalmazott modul: Programozás

Programozás II. ATM példa Dr. Iványi Péter

C++ programozási nyelv Struktúrák a C++ nyelvben

Tervminták I. (Sablonfüggvény, Stratégia, Egyke, Látogató) Testek térfogata Lények túlélési versenye

Interfészek. Programozás II. előadás. Szénási Sándor.

C++ programozási nyelv Konstruktorok-destruktorok

Osztály öröklődés. Öröklődés és polimorfizmus. Programozás II. előadás. Szénási Sándor.

Bevezetés a Programozásba II 12. előadás. Adatszerkezetek alkalmazása (Standard Template Library)

Objektumorientált Programozás C++ ADATSZERKEZETEK ÉS ALGORITMUSOK 2. GYAKORLAT

OOP. #6 (VMT és DMT) v :33:00. Eszterházy Károly Főiskola Információtechnológia tsz. Hernyák Zoltán adj.

1. Mi a fejállományok szerepe C és C++ nyelvben és hogyan használjuk őket? 2. Milyen alapvető változókat használhatunk a C és C++ nyelvben?

Programozás C++ -ban

Programozási nyelvek Java

Az OO paradigma. Mitől OO egy program? Objektum Osztály Öröklődés

Programozás BMEKOKAA146. Dr. Bécsi Tamás 7. előadás

Objektum Orientált Programozás. 11. Kivételkezelés 44/1B IT MAN

Bevezetés a programozásba II. 8. Előadás: Osztályok, objektumok, osztályszintű metódusok

osztályok kapcsolata Származtatatás C++ Izsó Tamás március 19. Izsó Tamás Származtatatás/ 1

Objektum orientált programozás Bevezetés

Absztrakció. Objektum orientált programozás Bevezetés. Általános Informatikai Tanszék Utolsó módosítás:

Átírás:

Pázmány Péter Katolikus Egyetem Információs Technológiai és Bionikai Kar Bevezetés a Programozásba II 8. előadás 2014.03.31. Giachetta Roberto groberto@inf.elte.hu http://people.inf.elte.hu/groberto

Öröklődés Objektumorientált programozásban kapcsolatot építhetünk ki osztályok között általánosabb-speciálisabb viszonylatban a speciálisabb osztály átveszi az általás működését, adatait, ezt öröklődésnek nevezzük pl.: class MyBaseClass { }; // ősosztály class MyChildClass : public MyBaseClass { } // leszármazott osztály az öröklődés feloldja a kódismétlődést, hiszen az ősosztályban definiálhatóak a közös részek, ugyanakkor a használatuk során az objektumok más típussal fognak rendelkezni (így másként kell kezelnünk őket) PPKE ITK, Bevezetés a programozásba II 8:2

Az öröklődésben Pl.: class MyBaseClass { protected: // leszármazottban látható mezők int _val; public: MyBaseClass() { _val = 1; } void PrintValue() { cout << _val; << endl; } }; class MyChildClass : public MyBaseClass { public: MyChildClass() { _val = 2; } // a konstruktor felülírja az értéket void DoSomething() { } } PPKE ITK, Bevezetés a programozásba II 8:3

Az öröklődésben Ha példányosítunk egy osztályt, akkor az objektum típusa az osztály lesz, pl.: MyChildClass mcc; ugyanakkor, ha az osztály leszármazott a példányban magában foglalja az ős minden tagját, így tekinthető az ős példányaként is vagyis öröklődés esetén a példányoknak egyszerre több típusa is adott (a konkrét osztály, és annak valamennyi őse), pl. mcc típusa MyChildClass, de egyben MyBaseClass is adott környezetben az objektum viselkedhet bármely típusának függvényében, és ez a környezetben szabályozható, ezt nevezzük polimorfizmusnak (többalakúságnak) PPKE ITK, Bevezetés a programozásba II 8:4

Dinamikus kötés Az objektumok létrehozhatóak dinamikusan is pl.: MyChildClass* mcp = new MyChildClass(); mcp->printvalue(); // kiírja: 2 az objektumra a típusának megfelelő mutató állítható rá, azonban a polimorfizmus miatt több típusa is lehet az objektumnak, így többféle mutató is alkalmazható, pl.: MyBaseClass* mbp = mcp; // az ős mutatóját állítjuk rá mbp->printvalue(); // kiírja: 2 tehát egy mutatót ráállíthatunk bármely leszármazott típusának egy példányára, ezt dinamikus kötésnek nevezzük PPKE ITK, Bevezetés a programozásba II 8:5

Statikus és dinamikus típus Dinamikus kötés esetén az ősosztály a változó statikus típusa, ezt értelmezi a fordítóprogram, ennek megfelelő tagokat hívhatunk meg statikus típusa több is lehet egy objektumnak a leszármazott a változó dinamikus típusa, futás közben az annak megfelelő viselkedést produkálja Pl.: MyBaseClass* mbp = new MyChildClass(); // mbp statikus típusa MyBaseClass, // dinamikus típusa MyChildClass MyChildClass* mcp = new MyChildClass(); // itt a kettő megegyezik PPKE ITK, Bevezetés a programozásba II 8:6

Statikus és dinamikus típus A dinamikus típus futás közben változtatható, mivel az ős típusú mutatóra tetszőleges leszármazott példányosítható pl.: MyBaseClass* mbp = new MyBaseClass(); mbp->printvalue(); // kiírja: 1 delete mbcp; mbp = new MyChildClass(); mbp->printvalue(); // kiírja: 2 ügyelni kell arra, hogy az ős mutatóján keresztül a leszármazott műveletei nem érhetőek el, pl.: mbp->dosomething(); // fordítási hiba, a statikus típusnak nincs // DoSomething művelete PPKE ITK, Bevezetés a programozásba II 8:7

Típuskonverzió A dinamikus típus műveleteinek elérésére típuskonverziót használhatunk (megfelelő ősosztállyal) típuskonverziót mutatókra biztonságos módon dynamic_cast<típus>(<mutató>) utasítással végezhetünk helytelen konverzió esetén NULL mutatót ad vissza Pl.: MyBaseClass* mbp = new MyChildClass(); if (dynamic_cast<mychildclass*>(mbp)) // ha konvertálható az adott típusra dynamic_cast<mychildclass*>(mbp) ->DoSomething(); // így már futtatható PPKE ITK, Bevezetés a programozásba II 8:8

Adatszerkezetbe szervezés A polimorfizmus azt is lehetővé teszi, hogy egy adatszerkezetben különböző típusú elemeket tároljunk az adatszerkezet elemtípusa az ős mutatója lesz, és az elemek dinamikus típusát tetszőlegesen váltogathatjuk Pl.: MyBaseClass* mbps[3]; mbps[0] = new MyBaseClass(); mbps[1] = new MyChildClass(); mbps[2] = new MyChildClass(); for (int i = 0; i < 3; i++) mbps[i]->printvalue(); // kiírja: 1 2 2 PPKE ITK, Bevezetés a programozásba II 8:9

Példa Feladat: Készítsünk egy programot, amelyben téglalapokat és köröket tudunk a képernyőre rajzolni, amelyek három színben (piros, fehér, zöld) váltakoznak. A színeket utólag le tudjuk cserélni (új véletlenszerű színre), és a teljes rajzot el tudjuk tolni egy vektorral valamilyen irányba. javítsunk a korábbi megoldáson azzal, hogy polimorfizmus segítségével egy közös vektorban tároljuk az összes adatot a vektor elemtípusa alakzat mutató (Shape*) lesz, az elemeket dinamikusan fogjuk létrehozni, majd a program végén törölni a speciális osztályokban lévő művelet eléréséhez típuskonverziót kell alkalmaznunk PPKE ITK, Bevezetés a programozásba II 8:10

Példa Megoldás (main.cpp): int main() { vector<shape*> shapes; // alakzatok vektora, amely mutatókat tárol if (iscircle) shapes.push_back(new Circle()); else shapes.push_back(new Rectangle()); // az alakzatokat dinamikusan hozzuk létre PPKE ITK, Bevezetés a programozásba II 8:11

Példa Megoldás (main.cpp): // a típust át kell alakítanunk a megfelelő // leszármazottra, de előre nem tudjuk melyikre // ezért mindkettőt kipróbáljuk Rectangle* rec = dynamic_cast<rectangle*>(shapes[i]); if (rec!= NULL && rec->contains()) { // a leszármazott mutatón keresztül már // elérhető az összes művelet shapes[i]->setcolor(); break; } Circle* cir = dynamic_cast<circle*>(shapes[i]); PPKE ITK, Bevezetés a programozásba II 8:12

Viselkedés felüldefiniálás A leszármazott amellett, hogy örököl minden tulajdonságot az őstől, lehetősége van felüldefiniálni (override) az örökölt viselkedést az örökölt metódusok törzsét átírhatja, de a szintaxisát nem (más szintaxis esetén túlterhelésnek minősül) a felüldefiniálható metódusokat nevezzük virtuális metódusoknak a konstruktor sohasem lehet virtuális az ősben előre kell jelezni, ha megengedjük a működés felüldefiniálhatóságát a virtual kulcsszóval a kulcsszó csak egy felüldefiniálást tesz lehetővé PPKE ITK, Bevezetés a programozásba II 8:13

Viselkedés felüldefiniálás Pl.: class MyBaseClass { public: virtual void PrintValue(){ cout << 1 << endl; } // felüldefiniálható (virtuális) metódus }; class MyChildClass : public MyBaseClass { public: void PrintValue(){ cout << 2 << endl; } // felüldefiniáló metódus void PrintBaseValue() { MyBaseClass::PrintValue(); } // ős metódusának meghívása }; PPKE ITK, Bevezetés a programozásba II 8:14

Viselkedés felüldefiniálás MyBaseClass mbc; mbc.printvalue(); // kiírja: 1 MyChildClass mcc; mcc.printvalue(); // kiírja: 2 mcc.printbasevalue(); // kiírja: 1 Azon metódusokat, amelyek nem definiálhatóak felül nevezzük véglegesítettnek tehát alapértelmezetten minden metódus véglegesített a konstruktor csak véglegesített lehet, viszont automatikusan meghívódik A virtuális műveleteket az osztálydiagramban dőlt betűvel jelöljük PPKE ITK, Bevezetés a programozásba II 8:15

Viselkedés felüldefiniálás esetén, amennyiben a metódus virtuális, életbe lép a viselkedés felüldefiniálás, és a dinamikus típus szerint kerül lefutásra, pl.: virtual void PrintValue() MyBaseClass* mbc = new MyChildClass(); mbc->printvalue(); // kiírja: 2 véglegesített, akkor csak elrejtés történik, amit a program nem vesz figyelembe, így a statikus típus szerint kerül lefutásra, pl.: void PrintValue() MyBaseClass* mbc = new MyChildClass(); mbc->printvalue(); // kiírja : 1 PPKE ITK, Bevezetés a programozásba II 8:16

Példa Feladat: Készítsünk egy programot, amelyben téglalapokat és köröket tudunk a képernyőre rajzolni, amelyek három színben (piros, fehér, zöld) váltakoznak. A színeket utólag le tudjuk cserélni (új véletlenszerű színre), és a teljes rajzot el tudjuk tolni egy vektorral valamilyen irányba. javítsunk a korábbi megoldáson azzal, hogy megadjuk az ősben a különböző tevékenységet végrehajtó műveleteket (contains, draw) virtuális műveletként, így nem kell típuskonverziót használnunk továbbra is a két speciális alakzat példányait helyezzük a vektorba, és azok típusa szerint fog lefutni a művelet PPKE ITK, Bevezetés a programozásba II 8:17

Példa Tervezés: class Drawing Shape # _color :Color # _point :Point + Shape(int, int) + Shape(int, int, int, int, int) + contains(int, int) :bool {query} + getx() :int {query} + gety() :int {query} + draw() :void {query} + setcolor(int, int, int) :void + move(vector) :void - _radious :int Circle + Circle(int, int, int) + Circle(int, int, int, int, int, int) + contains(int, int) :bool {query} + getradious() :int {query} + draw() :void {query} «friend» + operator<<(genv::canvas&, Circle) :genv::canvas& - _width :int - _height :int Rectangle + Rectangle(int, int, int, int) + Rectangle(int, int, int, int, int, int, int) + contains(int, int) :bool {query} + getwidth() :int {query} + getheight() :int {query} + draw() :void {query} «friend» + operator<<(genv::canvas&, Rectangle) :genv::canvas& PPKE ITK, Bevezetés a programozásba II 8:18

Példa Megoldás (shape.hpp): class Shape { // alakzat osztály virtual bool contains(int x, int y) const { return false; } // virtuális (felüldefiniálható), // alapértelmezetten hamisat ad vissza virtual void draw() const { } // virtuális (felüldefiniálható), // alapértelmezetten nem csinál semmit }; PPKE ITK, Bevezetés a programozásba II 8:19

Példa Megoldás (main.cpp): for (int i = shapes.size() - 1; i >= 0; i--) { // a műveletek meg vannak adva az ősben, így // nyugodtan meghívhatjuk őket if (shapes[i]->contains(ev.pos_x, ev.pos_y)) { // a dinamikus típus szerint fog // végrehajtódni a művelet shapes[i]->setcolor(); break; } } PPKE ITK, Bevezetés a programozásba II 8:20

Absztrakt metódusok Virtuális metódusok esetén a felüldefiniálás opcionális, ugyanakkor kötelezővé is tehető azáltal, hogy nem adjuk meg a metódus törzsét az ősben ekkor egy absztrakt, vagy tisztán virtuális metódust hozunk létre, amelyet a leszármazottnak kötelező felüldefiniálnia ekkor a törzs helyébe =0;-t kell írnunk Pl.: class MyBaseClass { public: virtual void PrintValue() = 0; // felüldefiniálandó (absztrakt) metódus }; PPKE ITK, Bevezetés a programozásba II 8:21

Absztrakt osztályok Amennyiben egy osztályban van absztrakt metódus, akkor az osztály nem példányosítható (mivel a metódusa nem végrehajtható), ekkor az osztályt absztrakt osztálynak nevezzük általában akkor hasznos, ha öröklődéssel fogjuk össze az osztályokat egy közös ősbe, de az őst nem akarjuk példányosítani, mert olyan általánosság mellett nem adható meg a működése egy osztály úgy is lehet absztrakt, hogy a konstruktorát elrejtjük a külvilág elől (ekkor szintén nem példányosítható) Absztrakt osztályokat, illetve metódusokat a osztálydiagramban dőlt betűvel jelöljük PPKE ITK, Bevezetés a programozásba II 8:22

Interfészek Pl.: MyBaseClass* mbc = new MyBaseClass(); // hiba, absztrakt osztály nem példányosítható MyBaseClass* mbc = new MyChildClass(); // a MyChildClass már példányosítható, mert ott // meg van adva a SomeMethod törzse Definiálhatunk speciális absztrakt osztályokat, amelyek nem tartalmaznak megvalósítást, csak felületet, ezek az interfészek interfészben csak publikus, absztrakt metódusok lehetnek leginkább többszörös öröklődés kapcsán használatosak az interfészeket megvalósítjuk (nem örököljük) PPKE ITK, Bevezetés a programozásba II 8:23

Interfészek Pl.: class MyInterface { // interfész public: virtual void PrintValue() = 0; }; // csak absztrakt függvényeket tartalmazhat class MyBaseClass : public MyInterface { public: virtual void PrintValue() { cout << 1 << endl; } // megvalósítjuk az interfészt, de a művelet // felüldefiniálható marad }; PPKE ITK, Bevezetés a programozásba II 8:24

Interfészek class MyChildClass : public MyBaseClass { public: void PrintValue() { cout << 2 << endl; } void PrintBaseValue() { MyBaseClass:: PrintValue(); // meghívjuk az ős metódusát } }; MyInterface* mi = new MyBaseClass(); mi->printvalue(); // kiírja: 1 mi = new MyChildClass(); mi->printvalue(); // kiírja: 2 PPKE ITK, Bevezetés a programozásba II 8:25

Példa Feladat: Javítsuk az egyetemi modellünket öröklődés és polimorfizmus segítségével. A program írja ki az összes egyetemi polgár nevét és Neptun kódját. létrehozzuk az egyetemi polgár (UniversityCitizen) absztrakt ősosztályt, amely tartalmazza a közös részeket a hallgató és oktató osztályokból, amelyek ennek leszármazottai a leszármazottak definiálják a newcourse() műveletet külön-külön, ezért az ősben tisztán virtuális lesz a főprogramban egy közös tömbben tároljuk a polgárokat, polimorfizmust használva PPKE ITK, Bevezetés a programozásba II 8:26

Példa Tervezés: class Class Model UniversityCitizen # _name :std::string # _neptuncode :std::string # _neptunpassword :std::string # _courses :std::vector<course*> UniversityStudent + name() :std::string {query} + neptuncode() :std::string {query} + courses() :std::vector<course*> {query} + numberofcourses() :int {query} + newcourse(course*) :void # UniversityCitizen(std::string&) - generatecode() :std::string - generatepassword() :std::string UniversityTeacher + UniversityTeacher(std::string&) + newcourse(course*) :void -_teacher -_courses * + UniversityStudent(std::string&) + numberofcredits() :int {query} + newcourse(course*) :void -_students * Course - _coursename :std::string - _teacher :UniversityTeacher* - _credits :int - _maxheadcount :unsigned int - _students :std::vector<const UniversityStudent*> + Course(std::string&, UniversityTeacher*, int, unsigned int) + newstudent(universitystudent*) :bool + name() :std::string {query} + teacher() :UniversityTeacher* {query} + credits() :int {query} + maxheadcount() :int {query} + currentheadcount() :int {query} PPKE ITK, Bevezetés a programozásba II 8:27

Példa Megoldás (universitystudent.hpp): class UniversityStudent : public UniversityCitizen { // hallgató osztálya, speciális egyetemi polgár public: UniversityStudent(const std::string& n); int numberofcredits() const; }; void newcourse(course* c); PPKE ITK, Bevezetés a programozásba II 8:28

Példa Megoldás (main.cpp): UniversityTeacher groberto("giachetta Roberto"); vector<universitycitizen*> citizens; citizens.push_back(&groberto); // polimorfizmust használunk cout << "Az egyetem polgárai: " << endl; for (int i = 0; i < citizens.size(); i++){ cout << citizens[i]->name() << ", NEPTUN: " << citizens[i]->neptuncode() << endl; } PPKE ITK, Bevezetés a programozásba II 8:29