Modellierung mit
UML
Loading

2.2 Klassen und Vererbung

Bei der Einführung von Klassen, Attributen, Methoden und von Vererbung wird in diesem Abschnitt, wie bereits diskutiert, eine Implementierungssicht zugrunde gelegt. Die Abbildung 2.2 enthält eine Einordnung der wichtigsten Begriffe für Klassendiagramme.

Klasse
Eine Klasse besteht aus einer Sammlung von Attributen und Methoden, die den Zustand und das Verhalten ihrer Instanzen (Objekte) festlegt. Klassen sind durch Assoziationen und Vererbungsbeziehungen miteinander verknüpft. Ein Klassenname erlaubt es, die Klasse zu identifizieren.
Attribut
Die Zustandskomponenten einer Klasse werden als Attribute bezeichnet. Sie beinhalten grundsätzlich Name und Typ.
Methode
Die Funktionalität einer Klasse ist in Methoden abgelegt. Eine Methode besteht aus einer Signatur und einem Rumpf, der die Implementierung beschreibt. Bei einer abstrakten Methode fehlt der Rumpf.
Modifikator
Zur Festlegung von Sichtbarkeit, Instanziierbarkeit und Veränderbarkeit des modifizierten Elements können die Modifikatoren public, protected, private, readonly, abstract, static und final auf Klassen, Methoden, Rollen und Attribute angewandt werden. Für die ersten vier genannten Modifikatoren gibt es in UML/P die graphischen Varianten „+“, „#“ und „-“ und „?“.
Konstanten
sind als spezielle Attribute mit den Modifikatoren static und final definiert.
Vererbung
Stehen zwei Klassen in Vererbungsbeziehung, so vererbt die Oberklasse ihre Attribute und Methoden an die Unterklasse. Die Unterklasse kann weitere Attribute und Methoden hinzufügen und Methoden redefinieren – soweit die Modifikatoren dies erlauben. Die Unterklasse bildet einen Subtyp der Oberklasse, der es nach dem Substitutionsprinzip erlaubt, Instanzen der Unterklasse dort einzusetzen, wo Instanzen der Oberklasse erforderlich sind.
Interface
Ein Interface (Schnittstelle) beschreibt die Signaturen einer Sammlung von Methoden. Im Gegensatz zur Klasse werden keine Attribute (nur Konstanten) und keine Methodenrümpfe angegeben. Interfaces sind verwandt zu abstrakten Klassen und können untereinander ebenfalls in einer Vererbungsbeziehung stehen.
Typ
ist ein Basisdatentyp wie int, eine Klasse oder ein Interface.
Interface-Implementierung
ist eine der Vererbung ähnliche Beziehung zwischen einem Interface und einer Klasse. Eine Klasse kann beliebig viele Interfaces implementieren.
Assoziation
ist eine binäre Beziehung zwischen Klassen, die zur Realisierung struktureller Information verwendet wird. Eine Assoziation durch einen Assoziationsnamen, für jedes Ende einen Rollennamen, eine Kardinalität und eine Angabe über die Navigationsrichtungen beschrieben.
Kardinalität.
Die Kardinalität (Multiplicity, auch: Multiplizität) wird für jedes Assoziationsende angegeben. Sie ist von der Form „0..1“, „1“ oder „“ und beschreibt, ob eine Assoziation in dieser Richtung optional oder eindeutig ist beziehungsweise mehrfache Bindung erlaubt.
Abbildung 2.2: Begriffsdefinition für Klassendiagramme

In Abbildung 2.3 ist ein einfaches Klassendiagramm bestehend aus einer Klasse und einem angehängten Kommentar zu sehen. Die kursiven Erläuterungen und die geschwungenen Pfeile gehören nicht zum Diagramm selbst. Sie dienen zur Beschreibung von Diagrammelementen. Die Darstellung einer Klasse wird typischerweise in drei Felder unterteilt. Im ersten Feld wird der Klassenname angegeben.

Lädt...
Abbildung 2.3: Klasse Auction im Klassendiagramm

2.2.1 Attribute

Das mittlere Feld einer Klassendefinition beschreibt die Liste von Attributen, die in dieser Klasse definiert werden. Die dargestellte Information über Attribute kann in mehrerer Hinsicht unvollständig sein. So kann ein Attribut mit oder ohne seinen Typ angegeben werden. Im Beispiel in Abbildung 2.3 sind bei allen vier Attributen die Datentypen angegeben. Im Hinblick auf die Zielsprache Java wurde die in der UML standardmäßig übliche Form „attribut: Typ“ durch die Java-konforme Fassung „Typ attribut“ ersetzt.

Für Attribute stehen mehrere Modifikatoren zur Verfügung, die die Attributeigenschaften genauer festlegen. UML stellt als kompakte Formen „+“ für public, „#“ für protected und „-“ für private zur Verfügung, um die Sichtbarkeit des Attributs für fremde Klassen zu beschreiben. „+“ ermöglicht einen generellen Zugriff, „#“ für Unterklassen und „-“ erlaubt Zugriff nur innerhalb der definierenden Klasse. Nicht im UML-Standard enthalten ist eine vierte, nur von UML/P angebotene Sichtbarkeitsangabe „?“, die ein Attribut als nur-lesbar (readonly) markiert. Ein so markiertes Attribut ist frei lesbar, darf aber nur in Unterklassen und der Klasse selbst modifiziert werden. Diese Sichtbarkeitsangabe wirkt also beim Lesen wie public und bei der Modifikation wie protected. Sie erweist sich bei der Modellierung als hilfreich, um die Zugriffsrechte noch feiner zu beschreiben.

Weitere aus der Programmiersprache Java zur Verfügung stehende Modifikatoren, wie beispielsweise static und final zur Beschreibung statischer und nicht-modifizierbarer Attribute können im Klassendiagramm ebenfalls genutzt werden. In Kombination dienen diese Modifikatoren zur Definition von Konstanten, jedoch werden Konstanten in Klassendiagrammen häufig weggelassen. Ein mit static markiertes Attribut wird auch als Klassenattribut bezeichnet und kann wie in Abbildung 2.4 gezeigt alternativ durch einen Unterstrich gekennzeichnet werden.

Lädt...
Abbildung 2.4: Klassenattribut und statische Methode

Die UML erlaubt abgeleitete Attribute die mit „/“ markiert, werden (siehe Abbildung 2.5). Bei einem abgeleiteten Attribut lässt sich sein Wert aus anderen Attributen desselben oder anderer Objekte sowie Assoziationen berechnen („ableiten“). Die Berechnungsformel wird typischerweise in Form einer Bedingung attr==... definiert. UML/P sieht dafür die Verwendung der in Kapitel 3 eingeführten OCL vor.

Lädt...
Abbildung 2.5: Abgeleitete Attribute

2.2.2 Methoden

Im dritten Feld einer Klassenrepräsentation werden Methoden mit Namen, Signaturen und ggf. Modifikatoren für Methoden dargestellt. Auch hier wird die Java-konforme Schreibweise Typ methode(Parameter) statt der offiziellen UML-Schreibweise methode(Parameter): Typ verwendet. Während Attribute den Zustand eines Objekts speichern, dienen Methoden dazu, bestimmte Aufgaben zu erledigen und Daten zu berechnen. Sie nutzen dazu die in Attributen gespeicherten Daten und rufen andere Methoden des eigenen oder anderer Objekte auf. Wie Java bietet auch die UML/P Methoden mit variabler Stelligkeit, die zum Beispiel in der Form Typ methode(Typ variable …) angegeben werden. Die Zugriffsrechte für Methoden können analog zu den Sichtbarkeiten für Attribute mit „+“, „#“ und „-“ gesteuert werden.

Weitere Modifikatoren für Methoden sind

  • static, um die Methode auch ohne instanziiertes Objekt zugänglich zu machen,
  • final, um die Methode für Unterklassen unveränderlich zu machen und
  • abstract, um anzuzeigen, dass die Methode in dieser Klasse nicht implementiert ist.

Genau wie bei Klassenattributen wird es in der UML bevorzugt, statische Methoden alternativ durch Unterstreichung darzustellen. Konstruktoren werden wie statische Methoden in der Form Klasse(Argumente) dargestellt und unterstrichen. Beinhaltet eine Klasse eine abstrakte Methode, so ist die Klasse selbst als abstrakt zu definieren. Die Klasse kann dann keine Objekte als Instanzen ausprägen. In Unterklassen können jedoch die abstrakten Methoden einer Klasse geeignet implementiert werden.

2.2.3 Vererbung

Zur Strukturierung von Klassen in überschaubare Hierarchien kann die Vererbungsbeziehung eingesetzt werden. Existieren mehrere Klassen mit teilweise übereinstimmenden Attributen oder Methoden, so können diese in eine gemeinsame Oberklasse faktorisiert werden. Abbildung 2.6 demonstriert dies anhand der Gemeinsamkeiten mehrerer im Auktionssystem vorkommender Nachrichtenarten.

Stehen zwei Klassen in Vererbungsbeziehung, so vererbt die Oberklasse ihre Attribute und Methoden an die Unterklasse. Die Unterklasse kann die Liste der Attribute und Methoden erweitern sowie Methoden umdefinieren – soweit die Modifikatoren der Oberklasse dies erlauben. Gleichzeitig bildet die Unterklasse einen Subtyp der Oberklasse, der es nach dem Substitutionsprinzip erlaubt, Instanzen der Unterklasse dort einzusetzen, wo Instanzen der Oberklasse erforderlich sind.

Lädt...
Abbildung 2.6: Vererbung und Interface-Implementierung

In Java erbt jede Klasse (bis auf Object) von genau einer Oberklasse. Jedoch kann eine Oberklasse viele Unterklassen besitzen, die ihrerseits weitere Unterklassen haben können. Durch die Nutzung der Vererbung als Strukturierungsmittel entsteht eine Vererbungshierarchie. Eine Oberklasse kann dabei als Verallgemeinerung (auch Generalisierung) ihrer Unterklassen angesehen werden, da ihre Attribute und Methodensignaturen die Gemeinsamkeiten aller Unterklassen festlegen. Steht in einer Vererbungshierarchie weniger die Codevererbung im Vordergrund, sondern die Strukturierung, so wird auch von Generalisierungshierarchie gesprochen. Insbesondere bei der Erhebung von Anforderungen und beim Grobdesign spielt der Aspekt der Generalisierung bei der Systemstrukturierung eine wesentliche Rolle.

Vererbung ist ein wesentliches Strukturierungsmittel objektorientierter Modellierung. Dennoch sollten tiefe Vererbungshierarchien vermieden werden, da sie die in der Vererbungsbeziehung stehenden Klassen und damit den darin enthaltenen Code stark koppeln. Zum Verständnis einer Unterklasse müssen sowohl die direkte als auch alle darüber liegenden Oberklassen verstanden werden.

2.2.4 Interfaces

Java bietet eine Spezialform der Klasse an, das Interface. Ein Interface besteht aus einer Menge von Methodensignaturen und Konstanten und wird vor allem zur Definition einer Schnittstelle zwischen Systemteilen (Komponenten) eingesetzt. In Abbildung 2.6 wird das Interface Serializable benutzt, um eine bestimmte Funktionalität von allen Klassen zu fordern, die dieses Interface implementieren.

Ein Interface wird wie eine Klasse durch ein Rechteck dargestellt und mit dem Stereotyp interface markiert. Genauso wie von einer abstrakten Klasse können von einem Interface nicht direkt Objekte instanziiert werden. Stattdessen müssen die angegebenen Methodensignaturen in Klassen realisiert werden, die das Interface implementieren. Auch können Interfaces außer Konstanten keine Attribute beinhalten.

Während in Java eine Klasse nur von einer Oberklasse erben darf, kann sie beliebig viele Interfaces implementieren. Ein Interface kann auch andere Interfaces erweitern und so in einer Subtyp-Beziehung zu den erweiterten Interfaces stehen. Dabei bindet das Subinterface die vom Superinterface definierten Methodensignaturen in die eigene Definition und erweitert diese, wie in Abbildung 2.7 an einem Ausschnitt aus der Java-Klassenbibliothek gezeigt, um zusätzliche Methoden.

Lädt...
Abbildung 2.7: Interface-Implementierung und -Erweiterung

Technisch gesehen sind Interfaces und Klassen sowie Vererbung und Interface-Implementierung jeweils ähnliche Konzepte. Vereinfachend wird deshalb in Zukunft häufig der Begriff Klasse als Oberbegriff für Klassen und Interfaces sowie Vererbung für die Vererbung zwischen Klassen, die Implementierungsbeziehung zwischen Interfaces und Klassen und für die Subtyp-Beziehung zwischen Interfaces verwendet. Diese Vereinfachung ist insbesondere in der Analyse und dem Grobdesign sinnvoll, wenn eine Entscheidung, ob eine Klasse instanziierbar, abstrakt oder ein Interface wird, noch nicht getroffen ist.


Bernhard Rumpe. Agile Modellierung mit UML. Springer 2012