Diagram klas - Class diagram
Widok logiczny w systemie 4+1 Kruchtena używany jest do modelowania części systemu oraz sposobów, w jaki one ze sobą współdziałają.
Ten widok tworzą zawyczaj diagramy:
- klas
- obiektów
- maszyny stanowej
- interakcji
Diagram klas - cechy:
- Zawiera informacje o statycznych związkach między elementami (klasami)
- Klasy są ściśle powiązane z technikami programowania zorientowanego obiektowo
- Są jednymi z istotniejszych diagramow w UML
Symbol klasy
- Symbolem klasy jest prostokąt, zwykle podzielony poziomymi liniami na trzy sekcje:
- nazwy
- atrybutów
- operacji
- W razie potrzeby może zostać uzupełniony dodatkowymi sekcjami (np. wyjątków)
Klasa - notacja
Podstawowe sposoby przedstawiania klas, różne poziomy szczegółowości
Cztery pola: nazwy, atrybutów, metod i dla użytkownika, np. w celu specyfikowania odpowiedzialności klasy. Możliwe są różne poziomy szczegółowości.

Pole nazwy klasy:
stereotyp nazwa_ klasy lista_wart_etyk
Pole atrybutów:
stereotyp dostępność nazwa_atrybutu : typ = wart_początkowa lista_wart_etyk
Pole metod:
stereotyp dostępność nazwa_metody (lista_arg) : typ_wart_zwracanej lista_wart_etykt
Poziomy dostępu:

Dostępności:
+ publiczna
- prywatna
# chroniona
~ zakres pakietu
lista_arg: rodzaj nazwa_arg : typ = wart_początkowa
rodzaj definiuje sposób, w jaki metoda korzysta z danego argumentu:
in: metoda może czytać argument, ale nie może go zmieniać
out: może zmieniać, nie może czytać
inout: może czytać i zmieniać
Wszystkie elementy specyfikacji klasy za wyjątkiem nazwy klasy są opcjonalne. Nazwa klasy to z reguły rzeczownik w liczbie pojedynczej.
Składniki statyczne
- Składniki mozna zadeklarować jako statyczne ? działające na rzecz klasy, nie obiektu
- Koncepcja identyczna jak w językach zorientowanych obiektowo
- Reprezentacją graficzną jest podkreślenie
Krotność
Krotność pozwala określić minimalną i maksymalną liczbę obiektów, jakie można powiązać z daną cechą:
- dolna granica..górna granica - przedział od-do
- 1 - dokładnie jeden obiekt
- 0..1 - opcjonalnie jeden obiekt
- 1..* - przynajmniej jeden obiekt
- 1, 3, 5 - konkretne liczby obiektów
- * - dowolna liczba obiektów
Krotność cechy wskazuje, ile obiektów można, a ile trzeba w niej zawrzeć. Krotność można określać jako ograniczenie dolne i górne, jednak oczywiste lub powtarzające się wartości graniczne można pomijać, np.. zapis 0..* jest skracany do *, a zapis 1..1 do 1. W praktyce programowania istotna jest krotność 0, 1 i dowolna, natomiast wartości dyskretne są mniej ważne, jako szczególne przypadki wymienionych trzech. W UMLu 2.0 dlatego formalnie usunięto możliwość podawania dowolnych liczb będących ograniczeniami, np. 2..4, jednak z uwagi na czytelność tego zapisu użycie go nie stanowi wielkiego błędu.
Atrybuty

Atrybuty wpisane
Atrybuty zadeklarowane poprzez asocjację
Ogólna deklaracja atrybutu wpisanego
[widoczność] nazwa [liczebność] [:typ] [=wartość początkowa]] [właściwość]
- właściwość changeable - bez ograniczeń
- addOnly - gdy liczebność jest większa niż jeden, można dodawać nowe wartości, ale raz dodane nie moga byc zmieniane
- readOnly, frozen - nie ma możliwości zmiany (jak const w C++)
- Przykład:
+ wysokosc : double = 10 frozen
Ogólna deklaracja operacji
[widoczność] nazwa [(lista_parametrów)] [: typ_wyniku] [właściwość]
gdzie lista parametrów:
[tryb] nazwa : typ [=wartość_domyślna]
tryb:
- in - wejściowy, niemoże być modyfikowany
- out - wyjściowy, może być modyfikowany
- inout - wejściowy, wyjściowy, może być modyfikowany
właściwość:
- leaf - funkcja niepolimorficzna (nie może być nadpisana)
- isQuerry - funkcja nie zmieniająca obiektu
- sequental, guarded, concurent (mają zastosowanie przy operacjach współbieżnych)
Nazwa funkcji pisana kursywą - funkcja wirtualna
Związki między klasami

Wymienione od najsłabszych:
- Zależność
- Asocjacja
- Agregacja częściowa
- Agregacja całkowita
- Dziedziczenie
Zależność - dependency
Zależność pomiędzy dwiema klasami informuje, że jedna z nich, aby używać obiektów innej, musi mieć o niej informacje. Zależność występuje, gdy zmiana specyfikacji jednej klasy, może powodować konieczność wprowadzania zmiany w innej klasie. Najczęściej używa sie zależności do pokazania, że jedna klasa używa innej jako parametru jakiejś operacji. Obie klasy są zależne od siebie nawzajem w cemu zapewnienia poprawnej pracy!
Zależności są najprostszym i najsłabszym rodzajem relacji łączących klasy. Oznaczają, że zmiana jednej z nich w pewien sposób wpływa na drugą, np.
- << call >> - operacje w klasie A wywołują operacje w klasie B
- << create >> - klasa A tworzy instancje klasy B
<< instantiate >> - obiekt A jest instancją klasy B - << use >> - do zaimplementowania klasy A wymagana jest klasa B

Asocjacja
Asocjacja reprezentuje czasowe powiązanie pomiędzy obiektami dwóch klas. Obiekty związane asocjacją są od siebie niezależne. Asocjacja jest też używana jako alternatywny (obok atrybutu) i równorzędny sposób zapisu cech klasy.

Asocjacje są silniejszymi relacjami niż zależności. Wskazują, że jeden obiekt jest związany z innym przez pewien okres czasu. Jednak czas życia obu obiektów nie jest od siebie zależny: usunięcie jednego nie powoduje usunięcia drugiego.
Relacje asocjacji są zwykle opisywane frazami "...posiada...", "...jest właścicielem...", jednak ich znaczenie często jest mylone z inną relacją - agregacją.
W przypadku asocjacji żaden obiekt nie jest właścicielem drugiego: nie tworzy go, nie zarządza nim, a moment usunięcia drugiego obiektu nie jest z nim związany. Z drugiej strony, obiekt powiązany asocjacją z drugim posiada referencję do niego, może się do niego odwołać etc. Asocjacje mogą posiadać nazwy, zwykle w postaci
czasownika, który pozwala przeczytać w języku naturalnym jej znaczenie, np. ?A posiada B?. Często pomija się jedną z nazw asocjacji dwukierunkowej, jeżeli jest ona jedynie stroną bierną drugiej nazwy, np. ?przechowuje? ? ?jest przechowywany?.
Asocjacja jest równoważna atrybutowi: UML nie rozróżnia obiektu, który
jest polem klasy od obiektu i jest z nią związany asocjacją. Warto jednak przyjąć konwencję, w której obiekty reprezentujące wartości (np. daty) oraz typy proste (liczby, napisy, znaki) są modelowane jako atrybuty, natomiast obiekty dostępne poprzez referencje ? są przedstawiane poprzez asocjacje.
Klasa asocjacyjna
Klasy asocjacyjne są związane z relacją asocjacji i opisują jej właściwości. Mają dostęp do innych obiektów uczestniczących w relacji

Klasa asocjacyjna umożliwia opisanie za pomocą atrybutów i operacji nie obiektu, ale właśnie samej asocjacji pomiędzy klasami. Informacje przechowywane w klasie asocjacyjnej nie są związane z żadną z klas uczestniczących w asocjacji, dlatego wygodnie jest stworzyć dodatkową klasę i powiązać ją z relacją. Klasy asocjacyjne są reprezentowane graficznie jako klasy połączone linią przerywaną z relacją asocjacji, której dotyczą.
Agregacja częściowa
Agregacja reprezentuje relację typu całość-część, w której część może należeć do kilku całości, a całość nie zarządza czasem istnienia części.

Agregacja jest silniejszą formą asocjacji. W przypadku tej relacji równowaga między powiązanymi klasami jest zaburzona: istnieje właściciel i obiekt podrzędny, które są ze sobą powiązane czasem swojego życia. Właściciel jednak nie jest wyłącznym właścicielem obiektu podrzędnego, zwykle też nie tworzy i nie usuwa go. Relacja agregacji jest zaznaczana linią łączącą klasy/obiekty, zakończoną białym rombem po stronie właściciela
Agregacja całkowita (kompozycja)
Agregacja całkowita jest relacją typu całość-część, w której całość jest wyłącznym właścicielem części, tworzy je i zarządza nimi.

Agregacja całkowita jest najsilniejszą relacją łączącą klasy. Reprezentuje relacje całość-część, w których części są tworzone i zarządzane przez obiekt reprezentujący całość. Ani całość, ani części nie mogą istnieć bez siebie, dlatego czasy ich istnienia są bardzo ściśle ze sobą związane i pokrywają się: w momencie usunięcie obiektu całości obiekty części są również usuwane. Typowa fraza związana z taką relacją to "...jest częścią...". Agregacja całkowita jest przedstawiana na diagramie podobnie jak agregacja częsciowa, przy czym romb jest wypełniony.
Uogólnienie - Dziedziczenie
Uogólnienie tworzy hierarchię klas, od ogólnych do bardziej szczegółowych. Pozwala wyłączyć części wspólne klas.


Uogólnienie posiada różne interpretacje. Na przykład, w modelu pojęciowym Katalog jest uogólnieniem Katalogu rzeczowego, jeżeli każda instancja Katalogu rzeczowego jest także instancją Katalogu. Uogólnienie w przypadku klas często jest traktowane jako synonim dziedziczenia, podczas gdy dziedziczenie jest tylko możliwą techniką uogólniania. Inną jest np. wykorzystanie interfejsów, które pozwalają utworzyć relację uogólnienia/uszczegółowienia pomiędzy typami (dziedziczenie interfejsu) lub klasą i interfejsem (implementacja interfejsu).
Interfejsy i klasy abstrakcyjne
Klasa abstrakcyjna
Klasa abstrakcyjna deklaruje wspólną funkcjonalność grupy klas. Nie może posiadać obiektów i musi definiować podklasy.
Interfejs
Interfejs - klasyfikator zawierający deklaracje właściwości i metod ale nie implementuje ich (definicja UML != np. Java)
Dwie reprezentacje graficzne:
- jak klasa
- jako kółko


Interfejs deklaruje grupę operacji bez podawania ich implementacji.

- Celem tworzenia klas abstrakcyjnych i interfejsów jest identyfikacja wspólnych zachowań różnych klas, które są realizowane w różny od siebie sposób. Użycie tych mechanizmów pozwala na wykorzystanie relacji uogólniania do ukrywania (hermetyzacji) szczegółów implementacji poszczególnych klas.
- Klasa abstrakcyjna reprezentuje wirtualny byt grupujący wspólną funkcjonalność kilku klas. Posiada ona sygnatury operacji (czyli deklaracje, że klasy tego typu będą akceptować takie komunikaty), ale nie definiuje ich implementacji.
- Podobną rolę pełni interfejs. Różnica polega na tym, że klasa abstrakcyjna może posiadać implementacje niektórych operacji, natomiast interfejs jest czysto abstrakcyjny (choć, oczywiście interfejs i klasa w pełni abstrakcyjna są pojęciowo niemal identyczne).
- Ponieważ klasy abstrakcyjne nie mogą bezpośrednio tworzyć swoich instancji (podobnie jak interfejsy, które z definicji nie reprezentują klas, a jedynie ich typy) dlatego konieczne jest tworzenie ich podklas, które zaimplementują odziedziczone abstrakcyjne metody. W przypadku interfejsu sytuacja jest identyczna.
- Przyjętym sposobem oznaczania klas i metod abstrakcyjnych jest zapisywanie ich pochyłą czcionką lub opatrywanie słowem kluczowym {abstract}.
Dziedziczenie wielokrotne
Dziedziczenie wielokrotne (wielodziedziczenie) ma miejsce, gdy klasa dziedziczy inwarianty z więcej niż jednej klasy.

Szablony klas
Szablon klasy określa, z jakimi innymi klasami (nie obiektami!) może współpracować podana klasa. Klasy te są przekazywane jako jej parametry. Klasa będąca uszczegółowieniem takiej klasy jest klasą związaną.

Szablony klas to pojęcie wywodzące się z języka C++. Oznaczają one klasy, których definicja wymaga podania argumentów będących innymi klasami. W ten sposób szablon klasy jest swego rodzaju niepełną klasą, która dopiero po ukonkretnieniu może zostać użyta.
Przykład diagramu klas- Aukcja internetowa

Diagram klas