Class diagram - diagram tříd

Základy

Diagram tříd spolu s diagramem komponent(component diagram) patří do skupiny diagramů struktur (structure diagram).

Diagram tříd zobrazuje statický pohled na systém, tj. zejména třídy (class) jako typy objektů, obsah tříd a statické vztahy, které mezi nimi existují. Může obsahovat též pakckages. Také může obsahovat elementy chování (behavioral), např. operace, ale jejich dynamika je vyjádřena jinými diagramy, jako jsou např. diagram stavového stroje (state machine diagram) nebo diagram komunikací (communication diagram).

Kromě této stránky se lze další souvislosti ohledně notace tříd dočíst i v sekci OO (konkrétně na stránce vysvětlující pojem třída).

Příklad diagramu tříd

class diagram, 7 kB

Na obrázku je příklad class diagramu z naší půjčovny videokazet :

  • vidíme zde třídy Zákazník, CKazeta, CRežisér a asociatovní třídu Výpůjčka
  • třída má v horním oddílu (compartment) název, v prostřením oddílu může být seznam atributů (např. u třídy Zákazník jsou to jméno, příjmení, ....) a ve spodním oddílu seznam operací (zde vraťPříjmení)
  • asociace mezi třídami je znázorněna (v naprosté většině případů) jako plná čára spojující dvě třídy; asociace může mít mnoho různých ozdob (adornments)
  • konkrétní zákazník může mít vypůjčenu žádnou, jednu nebo více kazet (zobrazeno pomocí "*" u asociace mezi třídami Zákazník a CKazeta, a to u konce připojeného ke třídě CKazeta)
  • konkrétní kazetu může mít zapůjčenu žádný nebo jeden zákazník (zobrazeno pomocí "0..1" na konci asociace připojeném ke třídě Zákazník)
  • Kazetu (resp. film) režíroval právě jeden režisér
  • protože asociace mezi zákazníkem a kazetou musí mít vlastní atributy (musí si pamatovat datum výpůjčky a datum, kdy by měla být kazeta vrácena), zavedli jsme asociativní třídu Výpůjčka

Další podrobnosti

Třída (class)

Třída může obsahovat nejenom tři compartments, ale i další (např. pro zobrazení odpovědností, seznamu obsluhovaných událostí, výjimek atd.; tyto compartments, narozdíl od standardních (název, atributy, operace) jsou pojmenovány : jméno oddílu je pak umístěno na začátku oddílu s odlišným fontem (pro rozlišení jména a obsahu oddílu)).

Atributy i operace mohou být zobrazeny po skupinách podle jejich viditelnosti (ad viditelnost viz níže).

Zobrazení atributů a operací může být potlačeno (např. když je v diagramu na třídu pouze odkazováno, ale v daném kontextu nejsou atributy a operace příliš důležité).

Atribut a jeho syntaxe

všechny složky, které může obsahovat atribut :
<<stereotyp>> viditelnost / jméno :typ násobnost =implicitní-hodnota {property-string}
      kde :

  • <<stereotyp>> : nepovinná část; viz popis obecných mechanismů UML
  • viditelnost : nepovinná část; definuje, odkud bude atribut viditelný a přístupný :
    -  soukromý (private)jen uvnitř třídy
    +veřejný (public) ze všech tříd
    #chráněný (protected) uvnitř třídy a jejich potomků
    ~balíček (package) jen z elementů uvnitř balíčku (ve kterém je tato třída) a z vnořených balíčků
    alternativně může být viditelnost zobrazena jako keyword v property-stringu
  • / : značí, že atribut je odvozený
  • jméno : povinná část; doporučení : dlouhá jména takto : dlouheJmeno
  • typ : nepovinná část; určuje, jaký typ objektu může být pamatován v atributu; většinou začíná velkým písmenem;
    typ může být vyjádřen v syntaxi cílového jazyka;
    zobrazení typu může být polačeno (ačkoliv v modelu může být typ specifikován)
  • násobnost : nepovinná část; pro určení polí (např. bydliště [4] : String znamená, že bydliště je složeno z pole 4 řetězců, název[1..3] znemaná, že název je pole jednoho až tří řetězců), nebo nullability (RČ[0..1] značí : rodné číslo může a nemussí být vyplněno, příjmení[1] značí, že příjmení musí být vyplněno);
    default (pokud je multiplicita vybechána) znamená [1];
    pokud je horní rozsah větší než jedna, tak v property-stringu může být určeno pořadí a unikátnost
  • implicitní-hodnota : nepovinná část; tuto hodnotu získá atribut ihned po vzniku instance, pokud není jeho hodnota specifikována během vytváření instance (použitelné pro inicializaci atributů objektu)
  • property-string : nepovinná část; umožňuje specifikovat další vlastnosti atributu, např. {readOnly} pro atribut, jehož hodnotu nelze měnit, {oredered bag} pro sadu setříděných hodnot s možnými duplicitami apod.,
Na atributy se vztahují samozřejmě standardní mechanismy - mohou mít stereotyp (viz výše), omezení, označené hodnoty.
Příklady :
  • jméno
  • jméno : String
  • -národnost : String="česká"
  • : když nebude explicitně uvedeno jinak, tak národnost bude česká
  • +kuřák : String {Ano, Ne} : atribut kuřák může nabývat jen hodnot "Ano" nebo "Ne"
  • <<optimalizace>> součet : int {důvod = jelo moc pomalu, dne = 6.5.2005} : má stereotyp a dvě označené hodnoty
  • početOsob : int
  • : třídní proměnná, celotřídní atribut

Operace a její syntaxe

Operace specifikuje transformaci stavu cílového objektu (a potenciálně stavu zbytku systému dosažitelného z cílového objektu) nebo dotaz (query), který vrací hodnotu volajícímu objektu.
Operace je spuštěna voláním (call), přičemž volající objekt přeruší zpracování a předá řízení volanému objektu až do toho okamžiku, kdy volaný objekt dokončí zpracování a předá řízení zpět volajícímu objektu. Volající objekt ale přeruší zpracování jen tehdy, pokud jde o synchronní volání. Pouze v případě synchornního volání může volající objekt vrátit zpět volajícímu objektu návratovou hodnotu.

Operace specifikuje výsledek chování, nikoliv vlastní chování. Vlastní chování může být specifikováno metodou (tj. procedurálním kódem implementujícím operaci), přechodem ve stavovém stroji (tj. operace je triggerem, který spouští (fire) přechod - změnu stavu), nebo něčím jiným.

Operace versus metoda : často jsou tyto pojmy zaměňovány, a většinou to ani nevadí. Někdy je rozlišení ovšem významné : např. předek má specifikovanou operaci, přičež má čtyři různé potomky a každý z nich (každý po svém) operaci předka předefinuje - máme tedy jednu společnou operaci, ale pět (!) různých metod.

všechny složky, které může obsahovat operace :
<<stereotyp>> viditelnost jméno (názevArgumentu: typArgumentu=základní hodnota, ....) : návratový-typ {property-string}
      kde :

  • <<stereotyp>> : stejná pravidla jako u atributu
  • viditelnost : stejná pravidla jako u atributu
  • jméno : stejná pravidla jako u atributu
  • základní hodnota : pokud určitý argument není v rámci volání operace vůbec předán, nastaví si jeho hodnotu na implicitní základní hodnotu volaná operace sama
  • návratový-typ : nepovinná část; obsahuje seznam jmen klasifikátorů (třídy, interfaces, datové typy) specifikujících, jakých typů budou návratové hodnoty; pokud je vynecháno, tak operace nevrací hodnotu (obdoba void v C ++); může být vraceno i více hodnot než jedna (nekteré programovací jazyky toto však nepodporují)
  • {property-string} : nepovinná část; umožňuje specifikovat další vlastnosti operace, např. výjimky (exceptions)
  • zobrazení seznamu argumentů i property-stringu může být potlačeno (buďto potlačeno obojí, nebo nic)

Samozřejmě i na metody vztahují standardní mechanismy - mohou mít stereotyp (viz výše), omezení, označené hodnoty.

Příklady :

  • inkrementuj()
  • -zvětšiSe(procento: int)
  • +nastavVěk(věk: int = 18) : nastaví věk na předanou hodnotu, pokud není nic předáno, pracuje tak jako by bylo předáno 18
  • +zjistiProspěch(RČ: String) : String {prospěl s vyznamenáním, prospěl, neprospěl} : jako výsledek metody může být vráceno jen prospěl s vyznamenáním, prospěl nebo neprospěl
  • <<optimalizace>> sečti(): int {důvod = jelo moc pomalu, dne = 6.5.2005} : má stereotyp a dvě označené hodnoty
  • zjistiPočet: int : třídní metoda, celotřídní metoda

Signatura operace

Každá operace (ze všech operací jednoho objektu) musí mít jedinečnou signaturu, aby bylo jednoznačné, která metoda objektu má být spuštěna. Signaturu tvoří
jméno operace, typy všech předávaných parametrů a typ návratové hodnoty.
Tzn. že třída může mít současně všechny tyto operace :

  • zvětšiMnožství()
  • zvětšiMnožství(koho: int)
  • zvětšiMnožství(koho: String)
  • zvětšiMnožství(koho: String, kdy: Date)
  • zvětšiMnožství(koho: String, kdy: Date) :int
  • zvětšiMnožství(koho: String, kdy: Date) :String
Každá z výše uvedených operací má jinou signaturu, tedy všechny tyto operace mohou současně existovat v jediné třídě : podle signatury použité při volání metody lze vždy jednoznačně určit, která metoda má být spuštěna.

PS.: konkrétní pravidla toho, co všechno je bráno jako signatura operace a co už ne, mohou být ovšem závislá na konkrétním cílovém jazyku. Např. dvě operace stejného jména s jedním parametrem stejného typu, který má u první operace směr in a u druhé operace směr out, mohou být u některých jazyků brány jako operace se společnou signaturou, a u jiných jako operace s různou signaturou.

Relace (relationship) v diagramu tříd

Relace mezi dvěma (popř. více než dvěma) třídami jsou asociace.
Pokud existuje asociace mezi třídami, je tím popsán vztah mezi instancemi těchto tříd.
Třída se může objevit i na více než jednom konci asociace.
Instance asociace (link) je n-tice (seřazený seznam) referencí na objekty, tj. link má přesně specifikováno, který jeho konec je připojen na který objekt. Asociace právě určuje kolekci takových linků. Tato kolekce může být typu set (položky se nesmí duplikovat) nebo bag (povoleny duplikace položek) a elementy mohou být nesetříděny (set/bag) nebo setříděny (set/list). Objekt se může objevit vícekrát v jedné sadě linků, a dokonce vícekrát u jednoho linku.
Link nemá vlastní identitu (kromě seznamu objektů, které jsou připojeny na jeho konce).
Asociace jsou jakýmsi lepidlem, které drží model systému pohromadě : bez asociací bychom měli jen sadu izolovaných tříd.

Příklad asociace :
asociace, 6 kB
  • název asociace : nepoviná část; říká, jak máme vztah číst, trojúhelníček udává směr čtení : muž je otcem ženy; směr čtení můžeme i obrátit, ale pak si musíme odpovídajícím způsobem upravit název vztahu : žena je dcerou muže
  • konec asociace : asociace má setříděný seznam dvou či více konců (setříděním je myšleno to, že konce jsou odlišitelné a nejsou zaměnitelné); každý konec asociace definuje účast jedné třídy v dané roli v dané asociaci;
    název role vyjadřuje, jaké role objekty daných tříd hrají, když jsou spojeny instancí této asociace; zde muž má roli otce, žena má roli dcery; vidíme zde redundanci - názvy rolí nám v podstatě říkají to stejné co názvy asociace : a skutečně, v praxi se používá u konkrétní asociace buď její název, nebo názvy rolí, použití obojího současně je nadbytečné (ale z hlediska následného programování je lépe používat role, neboť to usnadňuje provázání diagramu tříd a výsledného programu : role totiž mohou v programu korespondovat s názvy operací apod.)
  • násobost (multiplicity)
  • udává, jaký počet objektů se v libovolném okamžiku účastní vztahu; zde :
    • muž má libovolný počet dcer (žádnou dceru, jednu dceru nebo více dcer)
    • žena má vždy jednoho otce
    • žena ovšem může otce v čase měnit (např. dítě adoptuje jiný muž, ten se tak stane otcem dítěte, původní otec už není jeho otcem), žena však vždy musí mít právě jednoho otce (že muž může zemřít, nebo že otec může být "neuvedený", náš model jaksi nezohledňuje:-)
    Násobnost se udává ve tvaru minimum..maximum, popř. přesná hodnota. Implicitní násobnost je [1].
    Syntaxe násobnosti :
    1přesně jedna
    5přesně pět
    0..1nula nebo jedna
    *nula nebo více
    0..*nula nebo více
    1..*jedna nebo více
    2..8dva až osm
  • řiditelnost (navigability) určuje, že objekt zdrojové třídy vidí objekt cílové třídy, že mu může poslat zprávu. Objekt z cílové třídy na objekt zdrojové třídy nevidí, neví o něm a nemůže mu poslat zprávu (toto ale neplatí doslova - pokud nějak získá odkaz na zdrojový (či na jakýkoliv jiný) objekt, tak mu zprávu poslat může).
    V našem modelu otec zná všechny své dcery a kterékoliv dceři může poslat zprávu, ale dcera o svém otci neví (nemůže mu poslat zprávu).
    Asociace bez šipek je obousměrná (jakoby šipky byly na obou koncích), tj. objekty na sebe navzájem vidí a mohou si posílat zprávy (asociace zobrazená bez šipek ovšem může znamenat také to, že zobrazení šipek máme potlačeno).

Kam dál

Náměty na další studium

  • agregace, kompozice
  • generalizace (viz pojednání o třídě)
  • zvláštní typy generalizací (přesahující, rozpojená, hotová, nehotová)
  • keyword subset u asociace
  • keyword union u asociace
  • realizace
  • závislosti, standardní typy závislostí, standardní stereotypy závislostí
  • bidirectional asociace
  • constraints asociace
  • xor constraint (u asociace)
  • notace pro explicitní/implicitní křížení asociací
  • reflexivní (rekurzivní) asociace
  • vylučovací asociace
  • seřazená asociace
  • n-ární asociace
  • omezená asociace
  • specializace asociace
  • redefinice asociace
  • keywords pro třídění (ordering) a unikátnost (uniqueness) u multiplicit u asociací
  • property-string u asociace
  • notace pro not navigable konec asociace
  • visibility symbol u (navigable) konce asociace
  • derived asociace
  • spojení (merge) dvou či více agregací do jednoho konce asociace
  • modelování hierarchií a sítí
  • vnořené třídy
  • šablony, vzory
  • kvalifikátor
  • konstruktory, destruktory
  • multiple classification, dynamic classification
  • tempalte (parametrized) class
  • active class
  • rozhraní (interface)
  • zaměnitnost asociace a atributu třídy, asociace jako pseudoatribut
  • statický (třídní) atribut, statická (třídní) operace (viz pojednání o třídě)
  • notace pro skupinování atributů a operací dle jejich viditelnosti
  • další možnosti pro property-string atributu a operace
  • podrobnosti pro odvozený atribut, odvozená asociace
  • transient link
  • abstraktní operace (viz pojednání o třídě)
  • direction (směr) u parametru (in, out, inout, return) u operace
  • připojení těla metody (k operaci, kterou metoda impelementuje)
  • keyword <<signal>> u seznamu operací
  • keyword redefines u operace
  • constraints operace : precondition, postcondition, body condition
  • leaf operace
  • souběžnost (concurrency) operace, tj. násobné volání operace v rámci jedné instance : sequential, guarded, concurrent
  • balíčky