UML-Klassendiagramm: Sichtbarkeitsmodifikatoren

https://bildung.social/@oerinformatik/

https://oer-informatik.de/uml-klassendiagramm-sichtbarkeitsmodifikatoren

tl/dr; (ca. 4 min Lesezeit): Kapselung ist ein Konzept der OOP, das verhindern soll, dass Anpassungen des Codes zu Inkonsistenzen führen. Der Zustand der Objekte soll nicht direkt änderbar sein, sondern nur über Methoden, die ggf. weitere Anpassungen vornehmen können: Getter und Setter. (Zuletzt geändert am 24.05.2023)

Dieser Text ist ein Teil der Infotext-Serie zu UML-Klassendiagrammen:

Klassen sollten in der OOP so wenig wie möglich nach außen veröffentlichen. Attribute und Methoden, die lediglich den inneren Zustand eines Objekts betreffen, sollten von außen nicht erreichbar sein. Dadurch wird zum einen sichergestellt, dass bei Code-Anpassungen der inneren Struktur der Klasse keine Aufrufe von außen korrumpiert werden. Zum anderen erhält man so definierte Schnittstellen, über die Objekte nach außen kommunizieren. Plausibilisierungen, Zugriffskontrolle und Protokollierung beispielsweise können so viel einfacher umgesetzt werden.

Daher gibt es die Möglichkeit, Attribute und Methoden (“Member” einer Klasse) in Sichtbarkeit und Zugriff einzuschränken. Ich verwende im Folgenden “Sichtbarkeitsmodifikator” und “Zugriffsmodifikator” synonym und beschreibe mit beiden Begriffen das gleiche Konzept.

Zugriffsmodifikatoren

In der UML unterscheidet man vor allem Member, die nur innerhalb der Instanz einer Klasse zugreifbar und sichtbar sind (private, gekennzeichnet mit “-”) und Member, die auch von außen aufgerufen werden können (public, gekennzeichnet mit “+”). Bei Membern kann es sich sowohl um Attribute als auch um Methoden handeln. Weitere Varianten, die deutlich seltener benutzt werden, sind die Sichtbarkeit innerhalb einer Vererbungsstruktur (protected, “#”) und innerhalb von Namensräumen / Packages (package, “~”).

UML Klassendiagramm mit gekennzeichneten Sichtbarkeitsmodifikatoren vor Membern: - private, + public, # protected und ~ package
UML Klassendiagramm mit gekennzeichneten Sichtbarkeitsmodifikatoren vor Membern: - private, + public, # protected und ~ package

Eine verbreitete Art, die Sichtbarkeit von Membern über die Zugriffsmodifikatoren private und public zu konfigurieren, ist die Kapselung von Attributen.

Kapselung

Sinn und Zweck der Kapselung ist es, den inneren Zustand von Objekten zu verstecken. Hierbei werden Attribute versteckt (private) und nur durch öffentliche Zugriffsmethoden (Getter- und Settermethoden, public) von Außen verfügbar gemacht. Versteckt werden die Attribute, in dem sie über den Zugriffsmodifikator private nur innerhalb des Objekts zugreifbar sind. Je nachdem, ob die Attribute von Außen les- oder änderbar sein sollen werden öffentliche (public) Getter- und/oder Settermethoden erstellt:

Kapselung des Attributs iban mit Getter- und Setter-Methoden.
Kapselung des Attributs iban mit Getter- und Setter-Methoden.

In Java wäre die Implementierung folgendermaßen:

Der direkte Zugriff auf das Attribut von Außen wäre dann nicht mehr möglich (Auszug aus der Java-Shell):

Über die Getter- und Settermethoden kann jedoch zentral auf das Attribut zugegriffen werden.

Durch Kapselung wäre es möglich, dafür zu sorgen, dass nur gültige IBAN-Werte übergeben werden können. Ein zentraler Setter könnte absichern, dass die Gültigkeit einer IBAN immer geprüft ist.

An anderes Beispiel wäre eine Überprüfung des Kontostands, bevor Abhebungen den aktuellen Kontostand verändern. Ein Setter könnte prüfen, ob der resultierende Betrag kleiner als ein Dispolimit ist, und andernfalls die Anpassung verhindern (beispielsweise eine Exception werfen).

Soll beispielsweise eine Telefonnummer immer in internationaler Form ausgegeben werden, so kann es reichen, einen Getter anzupassen. Die Repräsentationsart, in welcher Form der Zustand eines Objekts nach außen dringt, kann somit auch nachträglich angepasst werden, ohne, dass der Zustand selbst veränder werden muss.

Zugriffsmodifikation innerhalb Vererbungshierarchien

Mit private annotierte Attribute und Methoden sind auch für Instanzen erbender Klassen nicht zugreifbar. Im Beispiel unten verfügt eine Instanz von PrivatKonto zwar intern über die Information iban, kann aber selbst nicht darauf zugreifen, das es als private gekennzeichnet ist. Die erbenden Klassen PrivatKonto und GeschaeftsKonto müssen also die Getter und Setter nutzen, um iban anzusprechen.

Als Zwischenstufe zwischen private und public kommt hier protected (#) ins Spiel: So annotierte Member sind nur innerhalb von Instanzen der eigenen Klasse oder innerhalb abgeleiteter Klassen der Vererbungsstruktur (Subklassen und Subsubklassen) sichtbar/ zugreifbar. Auf das Attribut kontostand können PrivatKonto und GeschaeftsKonto also auch ohne Getter und Setter direkt zugreifen, externe Instanzen aber nicht.

Protected Zugriffsmodifikatoren in Vererbungsstrukturen
Protected Zugriffsmodifikatoren in Vererbungsstrukturen

Im Java-Quellcode wird analog zur UML auch das Keyword protected genutzt. Für das Beispiel oben sieht der Codeauszug etwa so aus:

Python verfügt über kein Konzept, das Sichtbarkeiten auf Vererbungsstrukturen begrenzt.

Zugriffsmodifikation innerhalb von Namensräumen (Packages)

Die UML stellt zur Gliederung von Klassen Namensräume (Packages) zur Verfügung, in den meisten Programmiersprachen sind die unterschiedlichen Module in Packages organisiert. Um eine Möglichkeit zu schaffen, dass Member nicht komplett öffentlich zugreifbar sind, sondern nur innerhalb eines Namensraums, gibt es einen weiteren Zugriffsmodifikator package:

Package Zugriffsmodifikatoren in unterschiedlichen Namensräumen
Package Zugriffsmodifikatoren in unterschiedlichen Namensräumen

Im Beispiel oben ist der Konstruktor Konto() nur innerhalb des Paketes CRM nutzbar. Die Klasse Buchungen nutzt zwar ein Konto (und verfügt auch über ein Attribut vom Typ Konto), kann dieses jedoch selbst nicht erzeugen, da der Konstruktor paketsichtbar ist, und nicht für den Namensraum Abrechnung, in dem Buchungen ist. Buchungen ist also darauf angewiesen, dass extern ein Konto erzeugt wird und per Setter gesetzt wird. Danach kann Buchungen aber auf die public-Methoden von Konto zugreifen.

In Java ist Paketsichtbarkeit die default-Einstellung, daher werden dafür gar keine Sichtbarkeitsmodifizierer angegeben. Im Beispiel oben steht anstelle von public, private oder protected also nichts vor dem Konstruktor Konto():

In Python gibt es kein Konstrukt für Paketsichtbarkeit.

Übersicht der Zugriffsmodifikatoren

Im Ganzen gibt es vier Sichtbarkeitsmodifizierer wird im Rahmen der Vererbung / der Packages genauer eingegangen. Die Umsetzung der Berechtigungen in Java ist in folgender Tabelle wiedergegeben, für Python gibt es keine Entsprechungen:

Umsetzung in Java Darstellung
im
UML-
Klassen-
diagramm
sieht
eigene
Klasse
sieht
Klasse
im
gleichen
Paket
sieht
Unterklasse
im
anderen
Paket
sieht
Klasse
in anderem
Paket
privat:
private String iban
-iban ja nein nein nein
öffentlich:
public double getKontostand()
+getKontostand(): double ja ja ja ja
geschützt
protected double kontostand
#kontostand ja ja ja nein
paketsichtbar:
Konto()
~Konto() ja ja nein nein

Nächste Bestandteile des UML-Klassendiagramms:

In weiteren Artikel geht es um andere Eigenschaften des UML-Klassendiagramms, als Nächstes wird auf Objektbeziehungen (Assoziation, Aggregation, Komposition) eingegangen.


Hinweis zur Nachnutzung als Open Educational Resource (OER)

Dieser Artikel und seine Texte, Bilder, Grafiken, Code und sonstiger Inhalt sind - sofern nicht anders angegeben - lizenziert unter CC BY 4.0. Nennung gemäß TULLU-Regel bitte wie folgt: UML-Klassendiagramm: Sichtbarkeitsmodifikatoren” von oer-informatik.de (H. Stein), Lizenz: CC BY 4.0. Der Artikel wurde unter https://oer-informatik.de/uml-klassendiagramm-sichtbarkeitsmodifikatoren veröffentlicht, die Quelltexte sind in weiterverarbeitbarer Form verfügbar im Repository unter https://gitlab.com/oer-informatik/uml/umlklasse. Stand: 24.05.2023.

[Kommentare zum Artikel lesen, schreiben] / [Artikel teilen] / [gitlab-Issue zum Artikel schreiben]

Kommentare gerne per Mastodon, Verbesserungsvorschläge per gitlab issue (siehe oben). Beitrag teilen: