Osztály tervezési szempontok és C++ implementációs ajánlások

Hasonló dokumentumok
Osztálytervezés és implementációs ajánlások

Osztálytervezés és implementációs ajánlások

Osztálytervezés és C++ implementációs ajánlások I.

Osztály tervezési szempontok és C++ implementációs ajánlások

OOP. Alapelvek Elek Tibor

és az instanceof operátor

Objektum orientált programozás Bevezetés

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

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

C++ programozási nyelv

Már megismert fogalmak áttekintése

C++ programozási nyelv Konstruktorok-destruktorok

Eseménykezelés. Szoftvertervezés és -fejlesztés II. előadás. Szénási Sándor.

OOP és UML Áttekintés

Objektumok inicializálása

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?

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

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

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

C++ programozási nyelv

Objektumorientált paradigma és programfejlesztés Bevezető

JAVA PROGRAMOZÁS 2.ELŐADÁS

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

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

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

C++ referencia. Izsó Tamás február 17. A C++ nyelvben nagyon sok félreértés van a referenciával kapcsolatban. A Legyakoribb hibák:

Interfészek. PPT 2007/2008 tavasz.

Objektumorientált szoftverfejlesztés alapjai

Programozási nyelvek Java

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

Globális operátor overloading

Objektumorientált paradigma és a programfejlesztés

1. Bevezetés A C++ nem objektumorientált újdonságai 3

Java és web programozás

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

Programozás módszertan

Osztályok. 4. gyakorlat

Enterprise JavaBeans. Ficsor Lajos Általános Informatikai Tanszék Miskolci Egyetem. Az Enterprise JavaBeans

1. Öröklés Rétegelés Nyilvános öröklés - isa reláció Korlátozó öröklődés - has-a reláció

Programozás módszertan p.1/46

A Java EE 5 plattform

Programfejlesztési Modellek

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

Felhasználó által definiált adattípus

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

Származtatási mechanizmus a C++ nyelvben

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

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

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

Enterprise JavaBeans 1.4 platform (EJB 2.0)

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

Ficsor Lajos Általános Informatikai Tanszék Miskolci Egyetem

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

Programozási nyelvek Java

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.

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

3. Osztályok II. Programozás II

Objektumelvű programozás

Programozási nyelvek Java

Java VI. Egy kis kitérő: az UML. Osztály diagram. Általános Informatikai Tanszék Utolsó módosítás:

Java I. A Java programozási nyelv

Adatstruktúrák, algoritmusok, objektumok

Java III. I I. Osztálydefiníció (Bevezetés)

Programozás III KIINDULÁS. Különböző sportoló típusok vannak: futó, magasugró, focista, akik teljesítményét más-más módon határozzuk meg.

Java III. I I. Osztálydefiníció (Bevezetés)

Bevezetés a C++ programozási nyelvbe

Pénzügyi algoritmusok

A J2EE fejlesztési si platform (application. model) 1.4 platform. Ficsor Lajos Általános Informatikai Tanszék Miskolci Egyetem

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

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

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

Komponens alapú programozás Bevezetés

Osztály és objektum fogalma

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

A TANTÁRGY ADATLAPJA

Kivételkezelés a C++ nyelvben Bevezetés

OOP #14 (referencia-elv)

ELTE SAP Excellence Center Oktatóanyag 1

Bánsághi Anna 2014 Bánsághi Anna 1 of 33

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

Bevezetés a programozásba Előadás: Tagfüggvények, osztály, objektum

GENERIKUS PROGRAMOZÁS Osztálysablonok, Általános felépítésű függvények, Függvénynevek túlterhelése és. Függvénysablonok

Adatmodellezés. 1. Fogalmi modell

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

UML (Unified Modelling Language)

Konkurens TCP Szerver

Programozási Nyelvek: C++

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

Java VII. Polimorfizmus a Java nyelvben

C++ programozási nyelv Konstruktorok Gyakorlat

Bánsághi Anna 2014 Bánsághi Anna 1 of 31

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

Java VII. Polimorfizmus a Java nyelvben

Elemi Alkalmazások Fejlesztése II.

Java V. Osztályszint. lyszintű ű tagok. Példányváltozó. Osztályváltozó. Általános Informatikai Tanszék Utolsó módosítás:

500. AA Megoldó Alfréd AA 500.

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

Osztályok. construct () destruct() $b=new Book(); $b=null; unset ($b); book.php: <?php class Book { private $isbn; public $title;

C++ programozási nyelv

Átírás:

Miskolci Egyetem Általános Informatikai Tanszék Osztály tervezési szempontok és C++ implementációs ajánlások Oktatási segédlet levelező hallgatók részére Összeállította: Ficsor Lajos Miskolc 2005 1

Tartalomjegyzék 1. Bevezetés... 1 2. Az osztály fogalma... 1 3. Osztályok közötti kapcsolatok... 2 3.1 Az általánosítás / pontosítás kapcsolat (is-a)... 2 3.2. A tartalmazás kapcsolat (has-a)... 3 3.2.1. Az aggregáció implemetálása... 3 3.2.2. A kompozíció implementálása... 4 3.3. A használat kapcsolat (use)... 4 4. Az osztály interface... 5 4.1. Az osztály interface fogalma... 5 4.2. A jól tervezett osztály interface... 5 4.3. Az osztály interface részei... 6 4.4 Az elérési függvények... 6 5. Irodalomjegyzék... 7 i

1. Bevezetés Egy általános célú programozási nyelv szabályrendszere számos konstrukciót megenged. Egy szintaktikailag helyes (tehát a fordító által elfogadott és technikailag működőképes) program azonban tartalmazhat olyan részleteket, amelyek praktikus szempontok miatt kerülendők. Ezeket (valamint a jól használható konstrukciókat is) a programozók több évtizedes tapasztalatai jelölik ki. Egy szintaktikailag helyes és a gyakorlati tapasztalatok alapján kerülendőnek tartott konstrukciókat sem tartalmazó program már technikai szmepontból megfelelő, azonban még nem biztos, hogy értelmes feladatot old meg. A software fejlesztés feladata viszont épp egy adott, a gyakorlatban felmerült probléma megoldása. Ezért egy nyelv szintaktikai szabályainak ismerete csak szükséges, de nem elégséges feltétele annak, hogy a gyakorlati életben hasznot hajtó alkalmazást készítsünk. Az objektum orientált programozás a progamot a valóság valamely szeletének modelljeként tekinti. Ezért egy osztály megtervezése és implementálása olyan meggondolásokat is igényel, amelyek nem egyszerűen csak a C++ nyelv szabályainak alkalmazását jelentik. Ebben a részben tehát nem szintaktikai szabályokat fogunk ismertetni, hanem arra próbálunk példákat adni, hogy hogyan lehet jól használható, és az objektum orientált szemléletmódot tükröző osztályokat tervezni. Azaz: hogyan érdemes a C++ nyelv lehetőségeit használni. 2. Az osztály fogalma Az osztály programozástechnikai szempontból egy típus. Programtervezési szempontból az osztály a valóság valamely fogalmának modellje. Az objektum orientált programokban alapvetően kétféle osztályokat használunk: követlenül az alkalamazási terület (application domain) fogalmait modellező osztályok a feladat megoldásához technikailag szükséges implementációs osztályok. Az alkalmazási terület osztályai modellezhetnek felhasználói fogalmakat (például teherautó), felhasználói fogalmak általánosításait (például jármű). Az implementációs osztályok lehetnek az alábbiak modelljei: hardware / software erőforrások (például memória, i/o stb.) 1

más osztályok implementálásához szükséges osztályok (például listák, vermek) beépített adattípusok és vezérlési szerkezetek 3. Osztályok közötti kapcsolatok Az osztályok tervezése során foglalkozni kell az egyes osztályok közötti kapcsolatokkal. Az osztályok között a modellezés szempontjából különböző jellegű logikai kapcsolatok lehetnek (Általánosítás-pontosítás, tartalmazás, használat stb). Ugyanakkor a C++ nyelv biztosít olyan nyelvi szerkezeteket, amelyek implementációs kapcsolatokat teremtenek az osztályok között. Az osztály implementációja során az egyik feladat a logikai kapcsolatok leképezése ezekre a nyelvi szerkezetekre. 3.1 Az általánosítás / pontosítás kapcsolat (is-a) Implementációja a public leszármaztatás. Ez a kapcsolat azt jelenti, hogy egy leszármazott objektum minden szempontból úgy viselkedik, mint egy ős objektum, (azaz egy leszármazott objektum egyben mindig ős objektum is), de ez fordítva nem igaz. Egyszerű példa: class CSzemely { } class CHallgato : public CSzemely { } void sortiszik(const CSzemely& sz); void feladatotbead(cont CHallgato& h); Ezután CHallgato nagypista; CSzemely kispista; sortiszik(kispista); // OK // OK, mert egy Hallgato egyben Szemely is sortiszik(nagypista) // Hibás, mert egy Szemely nem biztos, hogy Hallgato is feladatotbead(kispista); Vigyázni kell azonban, mert a természetes nyelv nem mindig fogalmaz pontosan. Erre egy gyakran emlegetett tanpélda: class CMadar { public: void repul(void); 2

} class CStrucc : public CMadar { } Ebben az esetben a CStrucc osztály örökli a repülés képességét a CMadar osztálytól. A félreértést nyilván az okozza, hogy a "A madár tud repülni" mondat nem azt jelenti, hogy "Minden madár tud repülni", hanem azt, hogy "A madarak általában tudnak repülni". Egy lehetséges javítása a fenti példának az alábbi: class CMadar { public: CKaja MitEszik(void); Bool TudRepulni(void); } class Cstrucc : public CMadar { } Ebben az esetben a CStrucc osztály csak a repülés lehetőségét örökli a CMadar osztálytól, ami közelebb van a valóságos viszonyokhoz. Egy talán pontosabb javítás: class CMadar { public: CKaja MitEszik( void ) ; }; class CGyalogMadar : public CMadar { }; class CRendesMadar : public CMadar { public : void Repul( void ) ; }; class CStrucc : public CGyalogMadar{ }; class CSas : public CRendesMadar{ }; Ez a megoldás pontosabban tükrözi azt a tényt, hogy vannak repülni tudó és repülésre képtelen madarak is. 3.2. A tartalmazás kapcsolat (has-a) Kétféle tartalmazás jellegű kapcsolatot különböztethetünk meg: aggregáció: a rész az egészhez tartozik, de önállóan is létező entitás kompozíció: a rész önmagában nem létezhet, csak valaminek a részeként 3.2.1. Az aggregáció implemetálása Lehetséges megoldások: 3

a tag objektum pointere vagy referenciája a tartalmazó osztályban Hátránya, hogy szoros a kapcsolat a tartalmazó és a tartalmazott objektum között. Biztosítani kell a konzisztenciát, hiszen például a tartalmazott objektum megszűnése a rá vonatkozó pointer vagy referencia érvénytelenné válását jelenti. A tartalmazott private leszármaztatása a tartalmazó osztályból Ennek a megoldásnak a hátránya az, hogy a tartalmazott önálló voltát csak osztály szinten fejezi ki. 3.2.2. A kompozíció implementálása Lehetséges megoldások: tag objektum a tartalmazott osztályban lokális osztálydefiníció a tartalmazott számára 3.3. A használat kapcsolat (use) Osztályok az alábbi módokon használhatják egymást: CX használja a CY nevet (feltételezi, hogy CY deklarált a használat helyén) o adattag típusaként o tagfüggvény visszatérési értékének vagy paramétereinek típusaként CX használja a CY osztályt (láthatósági szabályok alapján) o meghívja a CY egy tagfüggvényét o írja/olvassa a CY egy adattagját CX létrehoz egy CY típusú objektumot o statikus definíció o dinamikus definíció CX veszi CY méretét A használat kapcsolat implementálásának alapvető problémája, hogy csak közvetett nyelvi eszközök jelzik az ilyen kapcsolatokat 4

Korlátozó tényezők: azonosítók lexikális érvényességi tartománya osztály tagjainak láthatósági attribútumai 4. Az osztály interface Az osztályokat úgy kell megtervezni, hogy azokat az interface-ük segítségével lehessen használni, anélkül, hogy az adattagok implementációjáról bármit is kellene tudni. Egy osztály megtervezése során gondolni kell arra, hogy azt bázisosztályként esetleg most még gondolatban sem létező osztályok is fogják használni. Ezért törekedni kell arra, hogy az esetleges leszármazott osztályokról csak a legszükségesebbeket tételezzük fel, és hogy egy leszármazott osztály tervezése során ne legyen szükség a bázisosztály implementációs részleteinek ismeretére (hiszen ez nem is biztos, hogy rendelkezésre áll). 4.1. Az osztály interface fogalma Egy osztály interface-e szűkebb értelemben a public tagfüggvényeinek összessége. Ezt kell ismernie az osztály használójának Tágabb értelemben ide számíthatjuk C++ programok esetén a friend függvényeket és osztályokat is. Ezt a lehetőséget azonban csak feltétlenül szükséges esetben használjuk, mert ellentmond az információ rejtés alapelvének A leszármazott osztályok számára még az osztály interface-ét képezik a protected függvények és adattagok is.ezzel is mértékletesen kell bánni, mert implementációs függést hoz létre az ős és a leszármazott osztály között. 4.2. A jól tervezett osztály interface A jó interface az alábbi három alapvető követelménynek kell megfeleljen: Legyen teljes, azaz minden olyan funkciót valósítson meg, amely az adott osztálytól elvárható (függetlenül attól, hogy a jelen alkalmazás során szükségesnek látszik-e). Az osztályt tehát funkció-orientáltan és ne az adott felhasználás szempontjából vizsgáljuk. Ezzel egyrészt újrafelhasználható elemeket alkotunk, másrészt nem korlátozzuk magunkat hiányzó funkciókkal a program további tervezése - készítése során. Legyen minimális, azaz ne legyen az interface része olyan funkció, amely a külső felhasználó számára érdektelen. Az adott osztály belső használatára szánt függvények legyenek mindig private (esetleg a leszármazott osztályokra is gondolva protected) módúak. Ezzel egyben megkönnyítjük az osztály esetleges áttervezését is: az adattagok és a segédfüggvények implementációjának módosítása a felhasználó program egyetlen pontján sem jelent változást. 5

Legyen kezelhető méretű. Ha a teljesség követelményének betartása túlságosan sok funkció megvalósítását eredményezi, az az osztály használójának munkáját nehezíti. (Egy programozó általában legfeljebb néhány tíz tagfüggvényt tart kezelhetőnek egy osztályon belül.) A sok funkció között nagyobb valószínűséggel lesznek hasonlóak, ami pedig könnyen vezet az egyes funkciók tényleges feladatának félreértéséhez. A terjedelmes interface mindig tervezési hibára utal, a két leggyakoribb ok: olyan funkciókat is az interface részének ítéltünk, amelyek inkább belső funkciók az osztály határait nem jól állapítottuk meg, és túl sok feladatot akarunk rábízni. A helyes architektúra kialakítása érdekében az eredetileg tervezett osztályt több osztályra kell bontani, és ezek között leszármaztatással vagy más mechanizmussal megteremteni a kapcsolatot. 4.3. Az osztály interface részei A public tagfüggvényeket funkciójuk szerint az alábbi csoportokba sorolhatjuk: kezelő függvények Idetartoznak az inicializáló, értékadó, konverziós stb. függvények, amelyeket sokszor nem is direkt módon a programozó aktivizál, hanem a fordítóprogram implicite hív meg. elérési függvények Az adattagok értékének elérésére vagy azok értékének módosítására. munkavégző függvények Az osztály lényegi funkcióit aktivizáló függvények. Míg a munkavégző függvények természetesen osztály-specifikusak, az első két csoportba tartozó függvények a különböző osztályok esetén is számos hasonlóságot mutatnak, előállításuk részben automatizálható is. 4.4 Az elérési függvények Az elérési függvények általában egyszerűek, implementálásuk értelemszerű. Segítségükkel az információ rejtés elvének megsértése nélkül tesszük használhatóvá az osztály objektumainak adattagjait. A kezelő fügvények megírása többletmunkát jelent, használatuk azonban a következő előnyöket biztosítja: Szabályozhatjuk azon adatok körét, amelyekhez egyáltalán hozzáférést biztosítunk az osztály objektumait használó program számára. 6

Szabályozhatjuk az egyes adattagok használatának módját (csak az értékét felhasználni, csak beállítani, vagy mindkét műveletre van-e módja a programnak). A függvények elrejtik a programozó elől az adattagok belső ábrázolásának implementációs részleteit, ezért ha azt megváltoztatjuk, az osztályt használó programban nem kell változtatni, ha ugyanolyan formában adjuk vissza a értéket. Például ha egy egész értéket ad vissza az alérési függvény, a felhasználó programozó számára lényegtelen, hogy az ténylegesen egy egész típusú adattag értéke, vagy esetleg egy bonyolult adatbázis lekérdezés eredménye. Természetesen, ha az adat tárlosi módja jelentősen eltér az elérési függvény által mutatott formátumtól, a megfelelő transzformációt biztosító függvény implementálása komoly programozói munkát is jelenthet. A kezelő függvényeket sok esetben a fejlesztő eszközök automatikusan generálni képesek, csökkentve ezzel az osztályt implementáló programozó munkáját. 5. Irodalomjegyzék Az alább felsorolt könyvekben amelyeket a jelen segédlet készítése során magam is felhasználtam a témára vonatkozó számos további információ található. Bjarne Stroustrup: A C++ progamozási nyelv Kiskapu Kiadó/ Addison-Wesley, Budapest, 2001. Scott Meyers: Hatékony C++ (50 jó tanács programjaink és programterveink javítására) Scolar Kiadó, Budapest, 2003 Bruce Eckel: Thinking In C++, 2 nd edition, Volume 1 Prentice Hall, 2000 Elérhető elektronikus formában a szerző honlapjáról (http://mindview.net), illetve a tanszéki szerveren található tükrözésről: http://www.iit.uni-miskolc.hu/bruceeckel. 7