Kihagyás

Objektumorientáltság alapfogalmak

Az előadás videója elérhető a itt.

Objektum- és osztálydiagram

Az objektum- és osztálydiagramok objektumok és osztályok vizuális reprezentációjára szolgálnak. Az osztálydiagram a rendszer "szótárának" is tekinthető, a rendszerben szereplő osztályokat és kapcsolataikat ábrázolja. Az objektumdiagramok pedig az osztály példányainak és kapcsolataiknak modellezésére szolgálnak. Objektum orientált tervezéshez nélkülözhetetlen mindkét diagram típus, jó kommunikációs eszközök.

Az objektum fogalma

Az objektum nem más, mint egy entitás ábrázolása, amely lehet akár a valós világ eleme, de lehet tetszőleg elvonatkoztatott elem. Például:

  • személy

  • poligon

  • kurzus

Minden objektum rendelkezik állapottal, viselkedéssel és identitással. Az állapot megadja az objektum egyes jellemzőit, a viselkedés megadja, hogy milyen módon reagálhat az objektum egy-egy őt ért üzenetre. Az identitás pedig annyit jelent, hogy minden objektum egyedi, még akkor is, ha az állapotuk azonos.Az identitás nyilván úgy valósul meg, hogy a minden objektumnak különálló memóriaterület van fenntartva (eltekintve a megosztott objektumoktól, de az más lapra tartozik).

A fentiek figyelembevételével először próbáljuk felfedezni, hogy milyen objektumok létezhetnek az alkalmazásunkban, majd az azonos állapottal és viselkedéssel (más objektumok felé, illetve belső szemantika) rendelkezőknek hozzunk létre osztályokat.

Objektum állapota, viselkedése, identitása

Az objektum állapota egy a lehetséges létezései közül, amely állapot az időben változhat. Az objektum állapotát az objektum attribútumai határozzák meg. Például egy Kurzus típusú objektum állapota nyitott, ha kevesebb, mint 20 fő jelentkezett rá, egyébként zárt, azaz nem jelentkezhet már rá több hallgató.

Annak módja, hogyan reagál egy objektum más objektumok kéréseire megadja az objektum viselkedését. Az osztály az operációk által definiálja, mi az, amit az objektum "csinálhat". Például egy Kurzus típusú objektumnak lehetnek hallgatófelvétel és hallgató_törlés operációi.

Minden objektum egyedi, akkor is, ha állapotuk azonos. Erre példa a programozás és algoritmusok objektumok, amik a Kurzusok osztálynak különböző objektumai.

Egy objektum UML diagrammja tartalmazza az objektum nevét, esetleg osztályát, azaz a típusát, és ha fontos, akkor pillanatbeli értékét az attribútumainak.

Osztály fogalma

Az osztály egy absztrakt adattípusnak tekinthető, amely olyan objektumok csoportjának a leírása, amely objektumoknak közösek az attribútumaik, operációik, más objektumokkal való kapcsolataik és szemantikus viselkedésük.

Az osztály egy minta objektumok létrehozásához (példányosításához): minden objektum pontosan egy osztály példánya, az osztály pedig az objektum típusa.

Az osztályok beazonosítás sokszor triviálisnak tűnik, de nagyobb rendszerek esetében ritkán egyértelmű az első ránézésre, hogy milyen egységekből legyen egy-egy osztály. Ilyen esetben mindig abból induljunk ki, hogy mik azok az objektumok, amelyek a rendszer futásakor képződhetnek. Ezt is általában az intuíciónk szerint végezzük, de nem árt, ha jobban megértjük, mi is rejlik a megérzéseink mögött.

Csomagok

Nagy rendszereknél elkerülhetetlen az osztályok csoportosítása. A csomagokkal hierarchikus szerkezetet biztosíthatunk a rendszerünkben. Egy magasabb absztrakciót valósíthatunk meg általuk a rendszerben. Minden csomag tartalmaz(hat) interfész osztályokat (amik publikusak, más által is elérhető) és implementációs osztályokat (amik belső, privát osztályok, csomagon kívül nem láthatóak).

A csomag UML jelölése egy olyan téglalap, amely tartalmazza az általa egybegyűjtött oszályokat, megnevezése pedig a téglalap tetején levő címkén van.

Osztálydiagramok

A csomagokba szervezett osztályok önmagukban nem elegendőek ahhoz, hogy a modellünk reprezentálja a rendszerünket. A modell különböző vetületei a tényleges megjelenítései a rendszernek. Általában minden csomaghoz tartozik egy fő diagram, valamint az egész rendszer logikai nézetéhez is tartozik egy fő diagram, amely a felsőszintű csomagokat ábrázolja. A csomagok fő diagramjai általában csak a csomag publikus osztályait tartalmazzák. A teljes diagramokhoz hozzátartoznak a kapcsolatok is, de ezeket később adjuk hozzá.

Kapcsolatok

Az eddig kialakított szerkezeti modellünket tovább bővíthetjük az osztályok közötti kapcsolatok megadásával. Egy-egy asszociációs kapcsolat (association) az osztályok között létrejövő objektum-kölcsönhatások megvalósulása, más szóval ezek a kapcsolatok adják az objektum-üzeneteknek a "csatornáit". Az asszociációs kapcsolat speciális fajtájaként említhetjük az aggregációs kapcsolatokat (rész-egész kapcsolatokat) (aggregation). Minden kapcsolatot különböző tulajdonságokkal fogunk kiegészíteni: név, irány, szerep, multiplicitás, stb. A már említett kapcsolatokon kívül az öröklődés (inheritance) pedig segíthet egy-egy osztály specializálásában, esetleg általánosításában. Gyengébb összefüggések ábrázolására megadhatunk függőségi kapcsolatokat. Illetve az osztályokon kívül, csomagok között is definiálhatunk bizonyos kapcsolatokat.

Asszociáció

Az általános asszociáció kapcsolat egy osztályok közötti kétirányú összeköttetés, amelynél navigálási irány adható meg az üzenet irányának jelzésére. Általában az asszociáció valamilyen használati kapcsolatot jelent a két osztály között, amelyek léte egymástól általában független, de legalább az egyik ismeri és/vagy használja a másikat (az ismeretség irányát megadhatjuk a navigálási irány segítségével). A kapcsolat szemantikus összefüggést ábrázol és nem adatfolyamot (mindkét irányba lehet információ/adat továbbítás). A valódi összefüggés az osztályokból létrejövő objektumok között jön létre, amely különböző kölcsönhatásokat jelent. UML jelölés szerint az asszociációs kapcsolat egyszerű tömör vonal a két osztály között, amelyekre különböző tulajdonságok is elhelyezhetők:

img

Aggregáció

Ez a kapcsolat az asszociáció egy speciális formája, amely "rész-egész" viszonyt fejez ki a résztvevő osztályok között (erősebb mint az asszociáció), vagyis azt, hogy az egyik objektum fizikailag tartalmazza vagy birtokolja a másikat. Ezt a kapcsolatot sok esetben nagyon nehéz precízen meghatározni, hiszen nem mindig egyértelmű, hogy a kapcsolat teljes vagy részleges tartalmazást jelent, vagy csak hivatkozást a másik objektumra. Egy asszociációból általában akkor célszerű aggregációt csinálni, amikor a kapcsolat leírásánál a "része" kifejezés egyértelműen használható, vagy amikor az egész-objektum bizonyos műveletei automatikusan a rész-objektumokra is vonatkoznak (például megszűnés).

UML jelölés szerint a rombusz a tartalmazó oldalán jelzi az aggregációt:

img

Alapvetően kétféle aggregációt különböztetünk meg:

  • gyenge tartalmazás – általános aggregáció (üres rombusszal jelölve)
  • erős tartalmazás, vagy más néven kompozíció – akkor használjuk amikor rész(ek) élettartama szigorúan megegyezik az egészével (teli rombusz) img

A kompozíciót általában könnyű felismerni például arról, hogy ha a tartalmazó megszűnik, akkor biztos a tartalmazottnak is meg szűnnie, vagy ha a tartalmazónak valamilyen műveletet kell végrehajtania, az minden esetben maga után vonja ugyanazon művelet végrehajtását a tartalmazotton is.

Az alábbi példa szemlélteti az általános asszociáció és a gyenge és erős aggregáció közti különbséget.

img

Öröklődés

Az általánosítás kapcsolat (Generalization) a UML-ben egy nagyon sokrétűen alkalmazható kapcsolat. Az újrafelhasználhatóság egyik alapeszköze. Osztály diagramok esetében az osztályok közötti öröklődés (Inheritance) ábrázolására használatos, amikor ugyanis az egyik osztály megosztja a struktúráját és/vagy a viselkedését egy vagy több másik osztállyal. Így egy öröklődési hierarchiát kapunk, ahol a származtatott osztály örököl az ősosztály(ok)tól (subclass derives from superclass). A UML értelmezése szerint, a származtatott (gyerek) osztály mindent örököl az őstől, beleértve a relációkat is. A UML általánosítás kapcsolatnak nincs neve és multiplicitás sem. Jele egy üres fejű nyíl, ami a speciálisabb osztálytól mutat az általános felé:

img

Ha már van egy csonka osztálymodellünk, amelyben osztályok már szerepelnek, a hozzájuk tartozó attribútumokkal, operációkkal és kapcsolatokkal, az öröklődések feltárása sokkal könnyebb mintha azzal kezdtük volna a tervezést. Két egyszerű elvet kell követnünk és a meglévő osztályokban keresnünk ahhoz, hogy előálljon az öröklődési hierarchia:

  • Általánosítás. Általánosításkor több osztály közös rész-struktúráját és -viselkedését egy közös ősosztályba helyezzük. Ez a tevékenység a tervezés kezdeti szakaszaira jellemző (legelőször a valós világot írjuk le majd később vonatkoztatunk el), tehát így célszerű kezdeni az öröklődések feltárását. Általános szabály, hogy az attribútumok, operációk és kapcsolatok a lehető legmagasabb szintre kerüljenek a hierarchiában! Például a StudentInformation és ProfessorInformation osztályoknak is vannak név, cím és telefonszám attribútumai, ezért kézenfekvő ezeknek egy közös ősosztályt létrehozni:

img

  • Specializálás. Specializáláskor származtatott osztályokat hozunk létre, amelyek finomítják az ősosztályt (tipikusan új struktúrát és viselkedést adnak hozzá).

A programjaink tervezésekor arra érdemes figyelni, hogy az öröklődési hierarchiák nagysága ne haladja meg a 3-5 szintet, ellenkező esetben a kódunk nehezen karbantarthatóvá válhat.

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

Többszörös öröklődésről beszélünk akkor, ha egy osztálynak több ősosztály-lánca van, azaz ugyanahhoz az őshöz több mint egy úton juthatunk el a hierarchiában (irányítatlan értelemben kör van benne). Például, a kétéltű jármű egy motorgépkocsi, ami egy jármű és az egy vízi jármű is ami ugyancsak egy jármű:

img

Ilyen többszörös öröklődéseket tartalmazó hierarchiák kezelésekor számos probléma adódhat, pl. név ütközések, többszörösen örökölt operációk/attribútumok, stb. Éppen ezért, számos programozási nyelv nem is támogatja a többszörös öröklődést (pl. Java). Egyéb nyelveken természetesen megoldható a probléma és kezelhető is, de csak nagy odafigyeléssel (pl. C++-ban virtuális öröklődéssel). Mindenesetre, kevésbé karbantartható kódhoz vezet ezért kerüljük a használatát.


Utolsó frissítés: 2021-05-04 07:53:32