Public oder Private oder Protected Sinn

  • Themenstarter Themenstarter Gelöschtes Mitglied 65838
  • Beginndatum Beginndatum
G

Gelöschtes Mitglied 65838

Gast
Hallo ich habe eine allgemeine Frage:
In der Schule würde mir gesagt dass Private "sicherer" ist als public

stimmt es dass private sicherer ist oder ist es nur gut um die Übersichtlichkeit zu erhöhen oder hat das einen weiteren Sinn


selbe Frage zu protected, wenn man einen code alleine schreibt bringt das nicht wirklich was weil man die Bedeutung weis...

Warum sollte man den "Aufwand" benutzen sich gedanken über die Sichtbarkeit zu machen?

Ich weis was die drei Wörter machen es geht um den Sinn
 
Wie soll ein Objekt Anforderungen (Invarianten) an seinen Zustand durchsetzen, wenn jeder Hans Dampf von außen in den Daten des Objekts rumwurschteln kann?
 
ist mit ausserhalb gemeint ausserhalb des programms oder wenn man mit mehr leuten an einem programm arbeitet
 
ist mit ausserhalb gemeint ausserhalb des programms oder wenn man mit mehr leuten an einem programm arbeitet
Damit ist gemeint von einer anderen Klasse.

Stell dir vor du hast eine Klasse Mensch, welche das Attribut Größe (kg, double) besitzt. Wäre das Attribut public könnte jeder von außen den Wert verändern wie er lustig ist. Hast du aber einen private Wert mit einem setter, kannst du über den setter den Wert auf Sinnhaftigkeit prüfen (z.B. nicht negativ) und ggf. eine InvalidArgumentException schmeißen.

Aus Perspektive der Erweiterbarkeit/Wartbarkeit macht man das nun schlichtweg immer, auch wenn getter und setter in vielen Fällen nur Einzeiler sind. Wenn du also später entscheidest eine solche Validierung zu ergänzen musst du nur noch den setter anpassen und nicht alle betroffenen Stellen von einem Attributzugriff auf einen Methodenaufruf umstellen.

Es gibt noch weitere Punkte, die in dieses Thema mit reinspielen. Sieh die obige Ausführung als Beispiel und nur als ein Kriterium von vielen.
 
Nur zu zwei Dingen was...

wenn man einen code alleine schreibt bringt das nicht wirklich was weil man die Bedeutung weis...
Nein. Sobald es etwas größer wird ("etwas größer" = alles über niedriger einstelliger Zahl), hat man keinen Überblick über das ganze und weiß nicht von allem die Bedeutung.

Du kannst natürlich versuchen dir zu merken, "Feld X in Klasse Y darf niemals geändert werden" oder "wenn Feld x geändert wird, muss auf jeden Fall auch Feld y geändert werden, in Abhängigkeit des Wertes von x und z" – aber das klappt einfach nicht.


Warum sollte man den "Aufwand" benutzen sich gedanken über die Sichtbarkeit zu machen?

"Sich Gedanken machen" ist die wesentliche Arbeit beim Software entwickeln, das Schreiben selbst ist nur eine "Nebensächlichkeit".
 
Zum Verständnis ist hier vielleicht wichtig, dies etwas einzuordnen:
Bei der Objektorientierten Entwicklung sind mehrere Konzepte wichtig und dazu gehören sowohl die Abstraktion als auch die (Daten)Kapselung.

Diese Prinzipien solltest Du Dir ggf. (z.B. mittels Google) etwas näher anschauen. Das zu kopieren und einzufügen bringt nicht wirklich viel.

Aber diese Prinzipien sind sehr wichtig. Nur als unscharfe, einfache Erläuterung: Dinge, auf die von außen nicht zugegriffen werden konnte, kannst Du beliebig ändern ohne dass irgend etwas anderes nicht mehr geht. Ein Zustand kann sich nicht unerwartet ändern.
 
Ich habe das auch am Anfang nicht verstanden, warum man einen Wert von außen nicht ändern soll und mit Set und Get Methoden rumeiern soll.

Aber wenn du mal folgendes bedenkst:

Eine Methode arbeitet oft nicht nur mit simplen Werten, sondern auch mit Validisierung von Werten, bzw. will mit den Werten weiter arbeiten.

Nehmen wir eine Klasse Mensch, wie im vorherigen Beispiel.

Ist dein Wert ein Integer und du fragst das Alter eines Menschen ab, kann der User Werte von−2.147.483.648 bis 2.147.483.647 eingeben. Solltest du mit diesen Werten an anderer Stelle rechnen, kann dies zu schweren Problemen bis zum Programmabsturz führen. Wenn Du also in deiner Funktion die Variable Mensch_Alter auf "private" setzt und das Alter per User Eingabe mit einer Setter Methode schreibst, kannst du gleichzeitig prüfen, ob das Alter im von Dir festgelegten gültigen Bereich von 0 - 120 (Oder was auch immer) ist und ggfls. den User auffordern ein gültiges Alter einzugeben.

Deswegen ist das vor allem sicherer.
 
wie meinst du das? dann kann ich doch gar nicchts mehr da machen 😱
Viele Setter sind ziemlich überflüssig, da die Variable entweder gar nicht geändert werden sollte, oder eine sinnvoller benannte Methode besser geeignet wäre.

Um mal bei dem Beispiel mit Menschen zu bleiben: Menschen haben ein Geburtsdatum und können Kinder haben, also etwa so:
Code:
class Mensch {
  Datum geburtsDatum;
  List<Mensch> kinder;
}

Mit "immer Setter nutzen" würde man jetzt einfach Setter für Geburtsdatum und Kinder hinzufügen, den für das Geburtsdatum vielleicht noch mir einer Überprüfung, dass das Datum in der Vergangenheit liegt.

Aber ist es sinnlvoll, wenn man das Geburtsdatum und die Kinder einfach ändern kann?
Geburtsdatum bekommt man bei der Geburt, und das ändert sich nie – also sollte man das auch genauso modellieren: Geburtsdatum im Konstruktor auf ein valides Datum setzen und dann jede Änderung verhindern.
Kinder "ändern" sich nicht, man kann neue bekommen, und vielleicht kann man auch welche "verlieren", aber beides ist keine einfache Änderung der Kinder, sondern viel sinnvoller über ein explizites (Namen ist extra abstrakt) addKind(Kind neuesKind) und vielleicht auch removeKind(Kind kind) abbilden.
 
wenn man einen code alleine schreibt bringt das nicht wirklich was weil man die Bedeutung weis...
Das ist in der Geschichte der Informatik einer der größten Irrtümer, denen ein Programmierer zum Opfer fallen kann.

Mein wichtigstes Projekt hat ca. 15 MB an Quellcode in über 900 Dateien (da sind private Klassen nicht mitgerechnet). Keine Chance, dass ich mir merken kann, welche Variable welcher Klasse wofür da ist. Dafür gibt's 1. Dokumentation und 2. geschützte Zugriffe.

Bei der ganzen Private/Package Protected/Public/Portected Frage geht es auch darum, dass der Code übersichtlich bleibt. Ein guter Algorithmus zeichnet sich nicht durch seine Länge aus. Spaghetticode ist ein großes Nono. Im Normalfall wird man ihn auf mehrere Methoden aufsplitten mit gut lesbaren Namen, deren Funktion auch verständlich wird, ohne dass man die Doku lesen muss.
Jetzt hast du in deiner Klasse 30 Methoden mit teils recht langen Namen, von denen 25 für die interne Berechnung genutzt werden. Warum sollten die publich sein? Das macht das Ganze nur unübersichtlich. Besser ist, diese von außen zu verbergen.

Wenn du was größeres entwickelst, denke nach Blackbox Muster. Wenn du eine Datei speichern willst, wirst du sicher nicht anfangen, die Schreibköpfe der Festplatte zu bewegen, oder? Nein, du überlässt das den entsprechenden in das Betriebssystem und die Firmware der Festplatte ingebetteten Programme.
Deine eigenen Projekte sollten ähnlich funktionieren. Von außen willst du nur sagen, was passieren soll. WIE das intern passiert, braucht und sollte dich von außen nicht interessieren.
 
Viele Setter sind ziemlich überflüssig, da die Variable entweder gar nicht geändert werden sollte, oder eine sinnvoller benannte Methode besser geeignet wäre.

Um mal bei dem Beispiel mit Menschen zu bleiben: Menschen haben ein Geburtsdatum und können Kinder haben, also etwa so:
Code:
class Mensch {
  Datum geburtsDatum;
  List<Mensch> kinder;
}

Mit "immer Setter nutzen" würde man jetzt einfach Setter für Geburtsdatum und Kinder hinzufügen, den für das Geburtsdatum vielleicht noch mir einer Überprüfung, dass das Datum in der Vergangenheit liegt.

Aber ist es sinnlvoll, wenn man das Geburtsdatum und die Kinder einfach ändern kann?
Geburtsdatum bekommt man bei der Geburt, und das ändert sich nie – also sollte man das auch genauso modellieren: Geburtsdatum im Konstruktor auf ein valides Datum setzen und dann jede Änderung verhindern.
Kinder "ändern" sich nicht, man kann neue bekommen, und vielleicht kann man auch welche "verlieren", aber beides ist keine einfache Änderung der Kinder, sondern viel sinnvoller über ein explizites (Namen ist extra abstrakt) addKind(Kind neuesKind) und vielleicht auch removeKind(Kind kind) abbilden.
Guter Beitrag, aber kommt es nicht darauf an, was man für eine Anwendung schreibt und wofür man das Alter braucht?

Klar, kann man, wenn eine Person zum Beispiel als User in einem System angelegt wird, das Alter oder, natürlich sinnvoller das Geburtsdatum aus dem sich das Alter ja errechnen lässt, einmal abfragen, und dann keinen Zugriff mehr zulassen. Wobei ich möglicherweise dann auch einen Zugriff brauche, denn das Geburtsdatum kann ja falsch angegeben worden sein. Und wenn ich so etwas dauerhaft speichere, dann speichere ich die Daten ja doch eher in einer Datenbank, als in einem Objekt.

Wenn ich aber ein kurzfristiges Objekt mit einem Menschen bilde. Sagen wir mal als Beispiel: Ich möchte altersgerechte Buch Vorschläge generieren, dann würde ich doch sehr wohl beim bilden des Objekts das Alter oder das Geburtsdatum, abfragen. Natürlich kann das als Parameter beim Start des Objektes geschehen und braucht keine Setter Methode. Aber ich könnte doch auch eine Klassen mit Buch Vorschläge haben, die läuft und ich versorge diese nur mit neuem Alter, um ein anderes Ergebnis zu bekommen.

Oder abstrakt gesagt : Starte ich eine Klasse oder ein Objekt mit Daten, die sich während der Laufzeit nicht mehr ändern, macht es natürlich Sinn, diese als Parameter zu übergeben und im Konstruktor abzuarbeiten. Ändern sich die Daten zur Laufzeit und sind diese zudem kritisch, weil ich beispielsweise die Validität von Daten beachten musst, ist es doch sinnvoll diese mit einer Setter Methode zu setzen.

Oder habe ich da ein grundsätzliches Verständnisproblem?
 
Guter Beitrag, aber kommt es nicht darauf an, was man für eine Anwendung schreibt und wofür man das Alter braucht?
Natürlich.
Wenn es möglich sein soll, das Geburtsdatum ändern zu können, dann muss ein Setter her, ansonsten nicht. Er hat ja nur ein Beispiel genannt, z.B. für eine Geburtsurkunde. Hier werden sich die Daten nie ändern.

Gehen wir mal einen Schritt weiter: Du speicherst das Geburtsdatum und willst das Alter wissen. Hier brauchst du noch nicht mal mal eine Variable, es reicht eine Berechnungsmethode. Ein Setter für das Alter wäre unsinnig.

Wenn es eine interne Methode gibt, die das Alter ändern können soll, aber es von außen nicht änderbar sein soll, dann wär's auch nicht gut, den Setter public zu machen, der sollte dann wie die Variable private sein.
Du kannst natürlich auch direkt reinschreiben, damit umgehst du aber sämtliche Kontrollen, die eventuell im Setter zu finden sind. Das ist ok, wenn das Alter nur an einer einzigen Stelle geändert wird, aber nicht, wenn es mehrere Zugriffe gibt.
Ein Setter kann auch protected sein, damit nur abgeleitete Klassen darauf zugreifen können.

Es gibt unzählige Szenarien und Beispiele, wann welche Sichtbarkeit sinnvoll ist. Man sollte halt immer nur das anbieten, was notwendig ist, damit erspart man sich viel Frust.
 
Wobei ich möglicherweise dann auch einen Zugriff brauche, denn das Geburtsdatum kann ja falsch angegeben worden sein. Und wenn ich so etwas dauerhaft speichere, dann speichere ich die Daten ja doch eher in einer Datenbank, als in einem Objekt.
Bei unveränderbaren Objekten gibt es auch die Möglichkeit, dass gesamte Objekt zu verwerfen und durch ein neues Objekt (mit entsprechend angepassten Eigenschaften) zu ersetzen. Siehe String in Java. Sie sind unveränderbar, wenn du einen String manipulierst, wird ein neuer String erzeugt.
 

Zurück
Oben