Objektum, osztály
Objektumelvű programozás Az elemzés együttműködő objektumok rendszereként fogalmazza meg a feladatot. Objektum-központú elemzés A tervezés a feladat tárgyköreit egy-egy objektum felelősségévé teszi, majd meghatározza az objektumok kapcsolatait. Objektum-alapú tervezés Objektumelvű programozás Objektum-orientált megvalósítás A megvalósítás objektum orientált nyelvi elemeket használ. Objektumonkénti tesztelés A (egység- és integrációs) tesztelés az objektumokra és azok kapcsolataira épül. 2
Objektum Objektumnak (object) nevezzük a feladat egy adott tárgyköréért felelős programegységét, amely tartalmazza a tárgykör megvalósításához szükséges adatokat és műveleteket. (pl: téglalap, verem) Modellezési szempontból az objektum a világ, azon belül a megoldandó probléma egy egyediként azonosítható része, amelynek adatait kizárólag ezen részhez tartozó műveletek kérhetik le vagy módosíthatják. Programozási szempontból egy olyan memória foglalás, amelyen tárolt értékeket csak ezen memóriafoglaláshoz rendelt alprogramok használhatnak fel és változtathatnak meg. 1 Az objektum-orientáltság lényeges ismérve az egységbezárás: egy adott tárgykör megvalósításához szükséges adatokat és az azokat manipuláló programrészeket egy egységként a program többi részétől elkülönítve adjuk meg. 3
Objektum életciklusa Az objektumok életciklussal rendelkeznek: létrejönnek (az objektum speciális műveletével, a konstruktorral), működnek, azaz a műveleteik révén saját adataikat manipulálják, továbbá más objektumokkal kommunikálnak: szinkron vagy aszinkron módon hívják egymás metódusait, vagy az egymásnak küldött jelzésekre (signal) reagálnak, megsemmisülnek (egy másik speciális művelettel, a destruktorral). Egy objektumnak állapotai (state) vannak: egy állapot az objektum adatai által felvett értékek együttese, amely a működés során változhat meg. A könnyebb érthetőség végett az objektum egy állapotának gyakran az objektum adati által felvett több lehetséges, de megadott tulajdonságú értékek együttesét tekintjük. 4
Objektum UML jelölése Egy objektumnak van osztálya, amely meghatározza az objektum attribútumait (tulajdonságait, adattagjait, mezőit) név-típus párok formájában és metódusait (műveleteit, tagfüggvényeit), amelyek az objektum adattagjainak értékeit manipulálják. neve (amit nem kötelező megadni) állapota (amit az összes adattagnév-érték pár alkot) <objektumnév>:<osztálynév> <adattagnév> = <érték> 5
Feladat Készítsünk olyan programot, amely feltölt egy tömböt különféle sokszögekkel, majd mindegyiket eltolja ugyanazon mértékkel, és kiszámolja az így nyert sokszögek súlypontjait. Egy sokszög csúcspontjainak és a súlypontoknak koordinátái legyenek egész számok. Objektumok: sokszögek, amelyeket egy tömbben tárolunk, síkbeli pontok, amelyek a sokszögek csúcsait és súlypontjukat adják. Objektumok felelősségi köre: sokszögek: eltolása, súlypontjának kiszámítása, adott csúcspontjának lekérdezése és módosítása, csúcsszámának lekérdezésére tömb: adott indexű elem elérése, hosszának lekérdezése síkbeli pontok: koordinátáinak lekérdezése és módosítása, eltolása 6
Példák objektumokra Pont objektumok: A:Pont x = 3 y = 4 B:Pont x = 7 y = -2 C:Pont x = 0 y = 1 D:Pont x = -4 y = -6 Sokszög objektum: Három:Sokszög Négy:Sokszög csúcsok = [ A, B, C ] csúcsok = [ A, B, C, D ] Tömb objektum: :Tömb elemek = [ Három, Négy] 7
Osztály Az osztály (class) az objektumok viselkedésének mintáját adja meg. Felsorolja az azonos viselkedésű objektumokban szereplő adattagok (tulajdonságok, attribútumok, mezők) neveit és típusait. Megadja az objektumokra meghívható (az objektum adattagjainak értékeit manipuláló) metódusokat (műveleteket, tagfüggvényeket) a visszatérési értékük típusával és az esetleges bemenő paramétereik neveivel és típusaival. Az osztály lényegében az objektum típusa: az objektumokat az osztályuk alapján hozzuk létre, azaz példányosítjuk. 8
Osztály fogalmának aspektusai Modellezési szempontból Ugyanazon attribútumokkal és műveletekkel rendelkező objektumok halmaza. Lehet absztrakt, amely osztályok halmazát írja le. Megadásához négy dolog tartozik: szolgáltatások (export) igényelt komponensek (import) megvalósítás (implementáció) paraméterek (pl. sablon) Programnyelvi megközelítés Ugyanazon adattagokkal és metódusokkal rendelkező objektumok leírása. Lehet hiányos leírású (absztrakt, speciálisan interfész), vagy sablon. Megadásakor az adattagjait és a metódusait kell jellemezni, amelyek lehetnek osztályszintűek is szabályozható a láthatóságuk 9
Osztály UML jelölése Egy osztálynak van neve, adattagjai, metódusai, illetve az adattagjainak és metódusainak láthatósága: publikus (+), illetve privát (-) vagy védett (#). Speciális osztályoknak tekinthetők a rekordok, amelyek általában metódusok nélküli, egyszerűsített adattárolási célú objektumok osztályai, felsorolási típusok (enumeration), amelyeknek csak az értékei ismertek. <osztálynév> <+ - #> <adattagnév> : <típus> <+ - #> <metódusnév>(<paraméterek>) : <típus> 10
Példák osztályokra Pontok osztálya: Pont objektumok: Pont - x : int - y : int + eltol(pont) : Pont A:Pont x = 3 y = 4 B:Pont x = 7 y = -2 C:Pont x = 0 y = 1 Sokszögek osztálya: Sokszög objektum: Sokszög - csúcsok : Pont[ ] + eltol(pont) : void + súlypont() : Pont :Sokszög csúcsok = [ A, B, C ] 11
Láthatóság az osztályokban Az osztály adattagjainak és metódusainak láthatósága lehet: kívülről is látható (public) rejtett (private, protected) Az osztály kívülről látható részét felületnek, vagy interfésznek, a rejtett részét implementációnak nevezzük. Az interfészt többnyire a metódusok egy részének fejei (név+szignatúra) alkotják; az osztály adattagjai és a metódusok törzse pedig az implementáció részei. Az adattagok értékéhez történő hozzáférést beállító (setter), illetve lekérdező (getter) műveletekkel szokás biztosítani. Ez ad lehetőséget az attribútumok ellenőrzött módosításra és feldolgozott lekérdezésre. 2 Az objektum orientáltság fontos ismérve az elrejtés: az egységbe zárt programrész bizonyos elemeinek láthatóságát korlátozzuk. (Általában az adattagok rejtettek, azok értékéhez csak közvetetten, a publikus metódusokkal férünk hozzá.) 12
Osztály és a típus összehasonlítása Osztály Az osztály példányai objektumok, amelyek attribútum-érték párok és metódusok egységei. Az osztály példányai dinamikusak: egy objektum egy attribútumának változtatásakor nem az objektum, csak annak állapota változik meg. Az objektum elemeinek láthatósága tetszőlegesen állítható. Lehetnek osztály szintű (azaz objektumok felett álló) elemei: adattagok és metódusok. Típus A típus egy típusérték-halmazt és az ezen értelmezett típus műveleteket adja meg. A típusértékek statikus fogalmak: egy típusérték egy összetevőjének megváltoztatásával másik típusértéket kapunk. A típusértékek összetevőit csak a műveletek látják, a műveletek viszont mind nyilvánosak. Nincsenek osztályszintű elemei. 13
reprezentáció típus-értékek Osztály vs. típus Osztály Típus Pont - x : int - y : int + eltol(p:pont) : Pont c = a.eltol(p) típus-specifikáció síkbeli pontok c := eltol(a,p) (ahol a,c,p pontok) típus-műveletek Pont c; c.x = x + p.x; c.y = y + p.y; return c; x,y : Z c.x, c.y := a.x+p.x, a.y+p.y implementáció típus-megvalósítás 14
Osztály-leírás kiegészítései Megszorításokat (invariáns feltételeket) írhatunk elő mind az adattagok értékére, mind a metódusok működésére az azok mellé írt { } jelzés közé. (Például az adattagokat nem módosító műveleteket a {query} jelzi.) Megadhatjuk egy mező kezdőértékét (amelyet majd a konstruktor állít be) Adhatunk sablonparamétert az osztálynak. Tulajdonságokat, illetve csoportba foglalásokat adhatunk meg a << >> jelzéssel magára az osztályra, vagy metódusainak illetve adattagjainak egyegy csoportjára nézve. (Például egy teljesen absztrakt osztályt az <<interface>> címkével jelezhetünk, vagy a getter metódusait a <<getter>> címke után sorolhatjuk fel.) <sablon> <osztálynév> - <adattagnév> : <típus> = <kezdőérték> { <feltétel>} + <metódusnév>(<paraméterek>) : <típus> {query} <<interface>> <osztálynév> <<csoport>> - <adattagnév> : <típus> <<getter>> + <metódusnév>() : <típus> 15
Osztály-leírás egyszerűsítése Az osztály-leírás a modellezés során fokozatosan alakul ki, ezért elfogadott, hogy a modellezés adott szintjén bizonyos részletek még hiányozzanak. Nem tartalmaz attribútumokat, metódusokat, vagy akár egyiket sem. Hiányozhat az adattag típusa, metódus esetén a visszatérési típus és a paraméterek. Nem kell szerepelnie a láthatósági jelöléseknek. Felsorolási típusoknál csak a felvehető értékeket adjuk meg (láthatóság nélkül. <osztálynév> <osztálynév> <osztálynév> <adattagnév> : <típus> <metódusnév>(<paraméterek>) : <típus> <metódusnév>(<paraméterek>) : <típus> 16
A feladat modellezésének szintjei Elemzés szintje Tervezés szintje Megvalósítás szintje x : int y : int eltol() Pont Tervezési döntések: adattagok közvetlenül nem érhetők el, csak a metódusok hívásán keresztül: pl. a.x = 2 egy érvénytelen hivatkozás getter-ek és setter-ek kellenek az eltolás nem az adott objektumot változtatja meg, hanem újat hoz létre: c = a.eltol(b); // c az a-hoz képest b-vel eltolt pont új művelet a súlypont kiszámításához Pont - x : int - y : int + eltol(p:pont) : Pont return Pont( _x+p._x, _y+p._y) return Pont( _x / f, _y / f) adattagok módosítása adattagok lekérdezése -_x : int -_y : int +Pont(int,int) Pont <<setter>> +newx(x:int) : void +newy(x:int) : void <<getter>> +x() : int +y() : int konstruktor, lehessen paraméter nélkül is hívni +eltol(p:pont) : Pont +operator+(p:pont) : Pont +operator/(f:int) : Pont c = a.eltol(b) helyett: c = a + b 17
Osztály-leírás kódolása Az osztályokat minden nyelv egy kicsit eltérő formában valósítja meg, de az általános jellemzőket megtartják. A C++ programozási nyelv is támogatja az objektumorientált programozást, noha program indítási pontja (main függvény) mindig procedurális. class/struct <osztálynév> { public/private/protected: <típus> <adattagnév>; <típus> <metódusnév> ([ <paraméterek> ]) { } }; 18
Osztály C++ kódja class Pont { public: Pont(int x = 0, int y = 0): _x(x), _y(y) { } }; void ujx(int x) { _x = x; } void ujy(int y) { _y = y; } int x() const { return _x; } int y() const { return _y; } default paraméter: Point a; Point b(3); Point c(-4,8); adattagok inicializálása Ezen metódus futása során az adattagok garantáltan nem változnak. Pont eltol(const Pont &p) const { return Pont(_x + p._x, _y + p._y ); } Pont operator+(const Pont &p) const { return Pont(_x + p._x, _y + p._y);} Pont operator/(int f) const { return Pont(_x / f, _y / f ); } private: int _x, _y; inline definíciók 19
Objektumok létrehozása Pont a(3,4); Pont c; c = a.eltol(pont(-1,-1)); eltol() hívása előtt: Ez a konstans adódik át a eltol()-beli p konstans paraméterváltozónak. c:pont _x = 0 _y = 0 = a:pont _x = 3 _y = 4 :Pont.eltol ( _x = -1 ) _y = -1 eltol() hívása után: c:pont _x = 2 _y = 3 értékadás :Pont _x = 2 _y = 3 Ez az eltol()-ban ideiglenesen létrehozott pont objektum, amelyet visszakapunk. Pont eltol(const Pont &p) const { return Pont(_x + p._x, _y + p._y ); } 20
Alapértelmezett másoló konstruktor és értékadás operátor Minden osztály rendelkezik az alábbiakhoz hasonló metódusokkal: Pont a(1,2); Pont b(a); vagy Pont b = a; Pont(const Pont &p); // másoló konstruktor Pont& operator=(const Pont &p); // értékadás operátor Pont a(1,2); Pont b, c; b = a; (vagy akár c = b = a;) tagonkénti másolás b:pont _x = 3 _y = 4 a:pont _x = 3 _y = 4 21