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
, “~”).

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:

In Java wäre die Implementierung folgendermaßen:
class Konto{
private String iban;
public String getIban() {
return iban;
}
public void setIban(String iban) {
this.iban = iban;
} }
Der direkte Zugriff auf das Attribut von Außen wäre dann nicht mehr möglich (Auszug aus der Java-Shell):
Konto konto1 = new Konto();
| konto1 ==> Konto@4671e53b
konto1.iban="DE123";
| Error:
| iban has private access in Konto
| konto1.iban="DE123";
| ^---------^
Ü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.

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
:

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ütztprotected 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.
Links und weitere Informationen
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]