Kapselung public / private verständis problem

kantaki

Mitglied
Hallo,
also ich weiß das man setters und getters public macht, und class variables private.

also ich dachte jedenfalls das ich es verstanden habe bis ich ein praktisches beispiel hatte.
undzwar programmiere ich gerade schiffeversenken.
Java:
public class Ships {
	private String name;
	private ArrayList<String> location = new ArrayList<String>();

	public ArrayList<String> getLocation() {
		return location;
	}

	public void setLocation(ArrayList<String> n) {
		location = n;
	}
ich denke bis jetzt drüfte noch alles richtig sein.
Bevor ich weiterschreibe sollte ich vielleicht noch sagen das location 3 strings beinhaltet
zb A0 A1 A2


Das input ist die benutzereingabe zb A0. JEtzt habe ich mir überlegt wie ich den String in location löschen kann, wenn er mit der benutzer eingabe übereinstimmt. buffer ist ein "remote control" (so stand es jedenfalls im buch) für die location arraylist.

[strike]Irgentwie fühlt es sicht aber nicht richtig an und ich bekomme auch immer einen runtime error.
sieht vielleicht irgentwer einen fatalen fehler in diesem codeschnipsel ?[/strike]
Java:
	public String gameCheck(Ships ship, String input) {
		String result = "miss";
		ArrayList<String> buffer = ship.getLocation();
		for (String count : ship.getLocation()) {
			if (count.equalsIgnoreCase(input)) {
				result = "Hit";
				buffer.remove(buffer.indexOf(count));

				if (buffer.size() == 0) {
					result = "Kill - GameOver";
					break;
				}
			}

		}

Java:
Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(Unknown Source)
	at java.util.ArrayList$Itr.next(Unknown Source)
	at Game.gameCheck(Game.java:14)
	at Game.gameStart(Game.java:41)
	at Game.main(Game.java:53)
zeile 14 ist
for (String count : ship.getLocation()) {
 
Zuletzt bearbeitet:
ups gerade gesehen das ich das break falsch gesetzt habe, daher kam der runtime fehler.
trotzdem.

ist es richtig hier
ArrayList<String> buffer = ship.getLocation();
...
buffer.remove(buffer.indexOf(count));
den wert so zu ändern ?
 
nein. Da bekommst du auch eine ConcurrentModificationException.
Wenn du in der Schleife Objekte aus der Liste entfernen willst musst du dir entweder alle Objekte in einer separaten Liste merken und später entfernen oder den Iterator nutzen, der bietet dir die Methode remove() an.
 
Hm, ich glaube nicht dass der TO (halb-)fertigen Code zum Thema schiffe versenken sucht. Die Frage war wohl eher wie die er die Exception los wird.
 
Ugh, wie kommst du auf die Idee, dass das mit den Getter und Setter Methoden in deiner Ship(s) Klasse eine gute Idee wär?
Womit der liebe Gassst wohl nicht sagen will, dass Datenkapselung keine gute Idee ist. Also das mit private ist schon korrekt. Aber in der Tat solltest du den Getter & Setter nochmal überdenken. Der Getter sollte - wenn du denn die gesamte List liefern willst - zumindest eine nicht-modifizierbare Liste liefern:

Java:
return Collections.unmodifiableList(location);

Also read-only. Sonst kann man die Location verändern ohne jemals den Setter aufgerufen zu haben, was ja wieder am Sinn von dem Ganze vorbeigeht.

Und bzgl des Setters ist es vllt auch besser lieber so Methoden wie moveLeft() etc anzubieten. Ist für den Caller angenehmer, und du kannst innerhalb der Klasse leichter kontrollieren was mit der Location geschieht.

Weiterhin solltest du deine Liste nicht als
Code:
ArrayList
deklarieren, sondern als
Code:
List
. Du musst wohl keine ArrayList-spezifischen Methhoden aufrufen. Stichwort Abstrahierung, Flexibilität usw.

Und nur um das nochmal zu unterstreichen: Dein Problem hat nichts mit public oder private zu tun.
 
Zuletzt bearbeitet:
okay danke für die vielen antworten.

du hast recht meine setter methode ist verbesserungswürdig.
allerdings bin ich noch nicht sehr weit in meinem buch dh list / unmodifizierte liste kenne ich halt noch nicht.

zum glück gibt es eine dokumentierte api
 
Womit der liebe Gassst wohl nicht sagen will, dass Datenkapselung keine gute Idee ist.

Im Gegenteil, Datenkapselung ist eine sehr gute Idee, leider ist in obigem Beispiel absolut gar nichts gekapselt oder versteckt, also genau das Gegenteil was man mit Datenkapselung erreichen will.

Ich habe das Gefühl von vielen, auch erfahrenen wie dir, Mitgliedern hier wird die "Variablen private, Getter & Setter" Geschichte wie ein Dogma heruntergebetet und als Allheilmittel für vernünftige Datenkapselung & Information Hiding postuliert. Das ist aber vollkommener Unsinn und wie man am obigen Beispiel sieht einfach nur falsch. Blöderweise wird sowas dann von weniger Erfahrenen Membern und Anfängern einfach unreflektiert nachgeplappert und man erhält Code wie den obigen...
 
Im Gegenteil, Datenkapselung ist eine sehr gute Idee, leider ist in obigem Beispiel absolut gar nichts gekapselt oder versteckt, also genau das Gegenteil was man mit Datenkapselung erreichen will.

Ich habe das Gefühl von vielen, auch erfahrenen wie dir, Mitgliedern hier wird die "Variablen private, Getter & Setter" Geschichte wie ein Dogma heruntergebetet und als Allheilmittel für vernünftige Datenkapselung & Information Hiding postuliert. Das ist aber vollkommener Unsinn und wie man am obigen Beispiel sieht einfach nur falsch. Blöderweise wird sowas dann von weniger Erfahrenen Membern und Anfängern einfach unreflektiert nachgeplappert und man erhält Code wie den obigen...
ich lese head first java und ich bin erst auf seite 150. mir wurde gesagt am anfgang sollte ich einfach jede class variable private machen setter getter public
 
Ich habe das Gefühl von vielen, auch erfahrenen wie dir, Mitgliedern hier wird die "Variablen private, Getter & Setter" Geschichte wie ein Dogma heruntergebetet und als Allheilmittel für vernünftige Datenkapselung & Information Hiding postuliert. Das ist aber vollkommener Unsinn und wie man am obigen Beispiel sieht einfach nur falsch. Blöderweise wird sowas dann von weniger Erfahrenen Membern und Anfängern einfach unreflektiert nachgeplappert und man erhält Code wie den obigen...
also soll man einen Anfaenger mit Information Hiding, Dependency Injection und Immutablity gleich volllabern ? gewiss der richtige ansatz !
 
mir wurde gesagt am anfgang sollte ich einfach jede class variable private machen setter getter public
Also das mit private stimmt. Zumindest wenn wir von Instanz-Variablen sprechen. Statische Variablen sind öfters mal public (zB Konstanten). Setter und Getter müssen aber nicht public sein. Der Sinn von dem ganzen ist im Endeffekt dass du im Setter eine kontrollierte Zuweisung machen kannst:

Java:
setX(X x){
  boolean xOkay = checkStuff();
  if(okay){
     this.x = x;
  }
  else{
     // Exception, oder was auch immer
  }
}

Das funktioniert natürlich unabhängig vom Access Modifier des Setters. public sollte er nur dann sein wenn eine außenstehende Instanz den Wert ändern können soll. Aber auch private Setter machen Sinn, da diese Kontrolle i.d.R. ja auch für Zugriffe aus der eigenen Klasse heraus gelten soll. Entsprechend sollte man auch bei Schreibzugriffen innerhalb der eigenen Klasse immer einen Setter verwenden, niemals eine Direkt-Zuweisung - auch wenn diese immer möglich ist. Aber man läuft Gefahr die Kontrolle des Setters zu umgehen.

Für den Getter gilt etwas ähnliches: Den schreibst du nur, wenn die entsprechende Information für außenstehende Instanz bekannt sein soll. Handelt es sich um irgendeine interne Hilfsvariable, gibt es keinen Grund das zu veröffentlichen. In dem Fall kannst (sollst!) du dir den Getter komplett sparen. Manche Leute schwören zwar auch hier auf einen private Getter, aber i.d.R. macht ein klassischer Getter nichts weiter als ein return des Wertes, da macht es also keinen Unterschied ob du den Lesezugriff über den Getter oder direkt machst.

Und als letztes gilt: Du kannst die "typischen" Getter/Setter auch gegen sinnvollere Methoden austauschen. Ein Getter muss nicht immer die entsprechende Variable returnen, und ein Setter muss nicht unbedingt als Parameter etwas nehmen, was der entsprechenden Instanz-Variable zu 100% gleicht. Zwei Beispiele die auch in deinem Fall passend sein könnten habe ich dir dafür genannt.

also soll man einen Anfaenger mit Information Hiding, Dependency Injection und Immutablity gleich volllabern ? gewiss der richtige ansatz !
Find ich schon. Mich stört es hier auch ein wenig dass man sich meist nur auf die eigentliche Fragestellung beschränkt. Wieso denn nicht ein Schritt weiter gehen und dem Fragesteller weitere Tipps geben? Wenn ihm dass dann zu heavy ist, kann er es noch immer ignorieren. Aber jmd der wirklich interessiert ist saugt solche Info-Häppchen nur zu gerne auf, so war/ist es bei mir zumindest. Wenn die Antwort immer nur von der eigentlichen Frage abhängt und kein Stück weiter, wird dieser Anfänger zu einem Fortgeschrittenen, und vllt auch Profi aber macht noch immer den selben S******. Immerhin kommt er nicht auf die Idee ein neues Topic aufzumachen mit der Frage "Information Hiding, Dependency Injection und Immutablity"
 
Zuletzt bearbeitet:
hmm... also dient das ganze einfach nur als schutz vor falschen zuweisungen. zb die instanz variable Zeit sollte nie negativ sein, also macht man eine simple if abfrage in der setter methode.

okay, müssen instanz variablen nun IMMER private sein? was wenn eine variable keine wert beschränkung hat, dürfte man in diesem fall die instanz variable public deklarieren ?

ups, das hast du schon in deinem ersten satz gesagt.

okay hat sich erledigt danke =)
 
hmm... also dient das ganze einfach nur als schutz vor falschen zuweisungen.
You got it! :toll: Zumindest was Setter angeht. Das private alleine dient erstmal dazu dass die Info nicht öffentlich bekannt gemacht wird.

okay, müssen instanz variablen nun IMMER private sein? was wenn eine variable keine wert beschränkung hat, dürfte man in diesem fall die instanz variable public deklarieren ?
Nein. Denn wer weiß, vllt willst du doch mal eine Beschränkung einführen. Wenn du von anfang an die variable private gemacht hast und über Setter arbeitest, musst du nur den Setter ändern und fertig. Wenn du Direkt-Zuweisungen hast darfst du deinen gesamten Code durchklappern um das an jeder Stelle zu ändern. Die Wahrhscienlichkeit dass du eine Stelle übersiehst ist recht groß. And that's where Bugs come from 😉
 
You got it! :toll: Zumindest was Setter angeht. Das private alleine dient erstmal dazu dass die Info nicht öffentlich bekannt gemacht wird.


Nein. Denn wer weiß, vllt willst du doch mal eine Beschränkung einführen. Wenn du von anfang an die variable private gemacht hast und über Setter arbeitest, musst du nur den Setter ändern und fertig. Wenn du Direkt-Zuweisungen hast darfst du deinen gesamten Code durchklappern um das an jeder Stelle zu ändern. Die Wahrhscienlichkeit dass du eine Stelle übersiehst ist recht groß. And that's where Bugs come from 😉

ah so langsam erkenne ich den vorteil von OOP =)
 
also soll man einen Anfaenger mit Information Hiding, Dependency Injection und Immutablity gleich volllabern ? gewiss der richtige ansatz !
Erklär mal wo ich das denn gesagt haben soll? Das kann man von mir aus halten wie man will. Ich sagte, dass man einem Anfänger nichts falsches beibringen soll und genausowenig Dogmen eintrichten soll. Da sollen sie ihre Felder lieber public lassen bis sie selbst irgendwann in ein Problem rennen.
 
Na das ist ja toll 😉 Tipp: Wenn du einen Satz in deinem Buch liest, nimm das nicht einfach so hin. Hinterfrage den Sinn davon. Wenn du etwas nicht nachvollziehen kannst, dann frag hier nach. In Lehrbüchern steht halt auch manchmal Mist. (Wobei es wahrscheinlicher ist, dass es einfach nur schlecht erklärt ist)
 
Da muss mich Gassst zustimmen,

Getter bieten erstmal keine Kapselung (sondern nur Information Hidung), Methoden machen Kapselung (wie getter) aber u.U. möglich.

Beispiel für einen Getter der keine Kapselung bietet aus dem Code des TS:
Java:
    public ArrayList<String> getLocation() {
        return location;
    }
[c]location[/c] ist hier eine mutable ArrayList, d.h. wenn man sich die location holt, kann man munter ausserhalb der Shipklasse daran ändern -> keine Kapselung
Der Setter hat übrigens dasselbe Problem, da kann man direkt von aussen den internen Zustand der Klasse ändern.

Zur Sache mit Gettern & Settern:
Für alle Attribute einen Getter & Setter zu machen kommt aus dem JavaBeans Standard, JavaBeans sind keine "richtigen" Objekte sondern nur Datenstrukturen, hätte man damals in der JavaBeans spec. die Getter & Setter weggelassen und nur public Fields draus gemacht, hätte man gar nix an Kapselung eingebüsst 😉

Wenn man keine JavaBEans, also "dumme" Datenstrukturen programmieren will, sollte man sich mehr Gedanken darüber machen wie die Schnittstelle des Objektes eigentlich aussehen soll.
 

Zurück
Oben