Warum setzt man Attribute einer Klasse auf private und verändert sie über Set und Get Methoden, was macht des für einen Unterschied?

8 Antworten

Die Idee der Kapselung ist, dass ein Objekt, welches Zugriff auf Attribute gewährt, durch Methoden kontrollieren kann, wer in welcher Form den Zustand des Objekts ändern kann.

Bspw. möchtest du ein Radio modellieren, welches eine bestimmte Lautstärke haben soll (von 0 bis 5 z.B.). Da man nicht davon ausgehen kann, dass die Werte, die man übergeben bekommt immer richtig sind (bspw. durch Eingabefehler oder mutwillige Fehler), kannst du über eine Set-Methode bestimmen, dass Änderungen nur dann erfolgen, wenn die Eingaben richtig sind (also irgendeinen Wert zwischen 0-5)

Wenn Du private Felder exponierst, dann

a) Werden von außerhalb eventuell Werte verändert, die zur Steuerung interner Zustände notwendig sein können.

b) Hast Du in der Klasse selbst keine Kontrolle mehr über die Schnittstelle und kannst auch nicht mehr an der Schnittstelle prüfen, gegebenenfalls Werte zurückweisen oder eine Exception werfen.

c) Kannst Du kein Interface deklarieren.

Die klassischen Argumente für den objektorientoerten Ansatz hast Du schon gelesen, denke ich. Ich versuch's mal praktisch zu erklären:

Man benutzt Objekte, Klassen etc, um sie wiederverwenden zu können, gern auch über viele verschiedene Projekte hinweg. Das geht nur, wenn man die Benutzung standardisiert, eben mit get und set Methoden. In der Dokumentation gibt man dann einfach die verfügbaren Getter und Setter an und jemand Anderes kann prima damit umgehen.

Wenn man die Variablen nicht auf private setzt, kann jeder von außen Unfug mit dem Objekt anstellen (natürlich auch man selbst) Das widerspricht aber der "Wiederbenutzungs-Fähigkeit".

Genau dieses Problem gibt es beispielsweise in Perl: Da kann man genau das tun: In einem Objekt ungehindert rummurksen, was zu viel Kritik an Perl geführt hat. Das lässt sich nur disziplinarisch lösen: Wer auf diese Weise in ein Objekt eingreift, gibt dem gesamten Team einen aus!

Halbwegs vertändlich?

Ist der übliche weg.

Debugging. Man kann ganz schlecht ne breakpunkt auf eine Variable setzen. Vorallem kann man aber sich entscheiden ob man das setzen oder lesen debuggen will.

Kontrolle. In einem getter oder setter kannst du noch weiteren code hinzufügen der bestimmte werte abbprüft. z.b. das man bestimmte werte nicht setzen kann. Oder das das Setzen eines wertes ein Event auslöst etc.

Zusätzlich kannst du auch so bestimmen ob variablen nur lesbar nach aussen sein sollen. Oder umgekehrt nur beschreibbar. (Eher selten, wenn überhaupt)

Noch zur kontrolle: Lazy loading wird so ermöglicht.

Anstatt alle variablen am anfang zu befüllen. Werden variablen nur dann befüllt wenn sie auch benötigt werden. Gerade wenn z.b. daten aus einer DB kommen oder aus einem anderen eher langsameren Prozess ist das sehr hilfreich weil die zeit die man dafür braucht sich aufteilt.

Auch kannst du so verhindern das man dir variablen unter dem po wegändert. z.b. sagen wir es wird was wichtiges in der klasse gerade gemacht und du brauchst die variable. entsprechend kann man darauf prüfen und entsprechend drauf reagieren. z.b. den vorgang abbrechen weil der user sich umendschieden hat und doch etwas anderes suchen will oder so. Oder man wartet mit dem setzen der variable einfach bis der prozess fertig ist etc.

Überschreibarkeit. Du kannst getter oder setter von abgeleiteten klassen überschreiben lassen um die funktionalität abzuändern.

Alle diese dinge sind nicht möglich wenn man Keine Getter/Setter benutzt

Der Hauptgrund dürfte ein konsistenter Zustand sein, den du mit öffentlichen Membervariablen unmöglich erreichen kannst.

Woher ich das weiß:Studium / Ausbildung