# Rückgabe einer Kopie bzw. Referenz



## Guest (11. Jan 2006)

Ich hab in einem Buch ein Programm entdeckt das nachfolgende Methode enthält. Es wird gefragt wo die Vor- bzw. Nachteile liegen, wenn man nicht direkt die Referenz auf das Attribut position, sondern eine vollständige Kopie des zweidemensionalen Feldes (wird durch die eingebaute Methode clone realisiert) zurückliefert.

Könnt ihr mir sagen was die Vor- und Nachteile sind?


```
public int[][] getPositions()
{
    return (int [][]) position.clone()
}
```


----------



## Sky (11. Jan 2006)

Nein. Das kommt auf die Anforderung an. 

Wenn das "Ursprungs-Array" erhalten bleiben soll, so biste natürlich mit ner Kopie besser beraten (und umgekehrt)


----------



## Guest (11. Jan 2006)

Mal angenommen das Ursprungsarray darf sich nicht ändern wo wären denn dann Vor- bzw. Nachteile. Ich will im Prinzip nur verstehen wann es sinnvoll ist eine Referenz zurückzugeben und wann eine Kopie


----------



## Guest (11. Jan 2006)

mein Problem ist das ich nicht weiss worauf die in diesem Buch mit der Frage hinaus wollen.


----------



## Sky (11. Jan 2006)

Lies mal dies: http://www.java-forum.org/de/viewtopic.php?t=5390


----------



## Guest (11. Jan 2006)

Vielleicht kannst Du dir die Aufgabe 2 der folgenden Klausur mal anschauen und mir an diesem Beipiel sagen wo die Vor- bzw. Nachtteile sind. Das wäre sehr nett.

hier der Link: Klausur

login: i 
password: studis


----------



## L-ectron-X (11. Jan 2006)

Wie wäre es, wenn du dich ein wenig selbst mit der Materie beschäftigst?
Wir machen hier keine Hausaufgaben, beantworten aber gerne konkrete Fragen. Ganz besonders, wenn wir erkennen können, dass sich der Fragende bemüht, mitdenkt und etwas lernen will.
Anderenfalls hast du keine gute Note verdient.


----------



## Guest (11. Jan 2006)

:meld:


----------



## Guest (12. Jan 2006)

Grundsätzlich würde ich folgendes gelten lassen: Wird ein Objekt/Array etc. intern, innerhalb der Klasse, 
die es liefert, verwendet, dann immer eine Kopie oder einen ImmutableWrapper zurückgeben, sonst direkt 
die Referenz des Originals. Ausnahmen wären Frameworks, wo solche Kopierereien aus Performancegründen 
nicht akzeptabel sind. Es sollte dann aber ausführlich dokumentiert werden.


----------



## André Uhres (12. Jan 2006)

Wenn das Objekt eine Konstante sein soll, soll es immer immutable sein.
Wenn das Objekt oft geändert wird, sollte es mutable sein.
Wenn das Objekt sehr gross ist sollte es wahrscheinlich mutable sein, weil das Kopieren
das Programm langsamer macht.
Sets und andere collections die von einer Methode zurückgegeben werden sollten immutable sein
um die Kapselung zu bewahren.


----------



## Sky (12. Jan 2006)

Anonymous hat gesagt.:
			
		

> Grundsätzlich würde ich folgendes gelten lassen: Wird ein Objekt/Array etc. intern, innerhalb der Klasse,
> die es liefert, verwendet, dann immer eine Kopie oder einen ImmutableWrapper zurückgeben, sonst direkt
> die Referenz des Originals. Ausnahmen wären Frameworks, wo solche Kopierereien aus Performancegründen
> nicht akzeptabel sind. Es sollte dann aber ausführlich dokumentiert werden.


Kannst Du das auch begründen ?


----------



## Guest (12. Jan 2006)

Sky hat gesagt.:
			
		

> Anonymous hat gesagt.:
> 
> 
> 
> ...


Gerne. Interna einer Klasse sollte man nicht nach aussen transportieren, da alles was ausserhalb einer Klasse 
geschieht, aus Sicht der Klasse nicht kontrollierbar ist. Gibst du eine Arrayreferenz zurück, kannst du dich nie 
darauf verlassen, was mit den Inhalten geschieht. z.B. es wird ausserhalb der Klasse umsortiert, während du
intern, in der Klasse, davon ausgehst, dass die Arrayelemente aufsteigend sortiert sind. Man könnte fragen, 
wer macht solchen Blödsinn? Fehlerquellen auszuschliessen gehört zum guten Programmierstill.
Alternative: Innerhalb der Klasse immer für korrekte Sortierung sorgen. Folge: Unnötige Sortierung, wenn
sich nichts geändert hat.

Beispiel aus Swing. DefaultTableModel und die Methode getDataVector() (OK, die ist protected). Jeder zweite 
Anfänger macht den Fehler, dass er sich nicht an die "Spielregeln" des Models hält und bei Änderungen 
die fire.... Methode nicht aufruft. Ich habe schon bei Codereviews so manche Swing-Akrobatik erlebt, wo 
jemand das Model nach Änderungen immer wieder neu gesetzt hat, damit die Änderungen wirksam werden.


----------



## Guest (12. Jan 2006)

Vielen Dank, auf so eine Antwort hab ich gehofft  :lol: 



> Wie wäre es, wenn du dich ein wenig selbst mit der Materie beschäftigst?
> Wir machen hier keine Hausaufgaben, beantworten aber gerne konkrete Fragen. Ganz besonders, wenn wir erkennen können, dass sich der Fragende bemüht, mitdenkt und etwas lernen will.
> Anderenfalls hast du keine gute Note verdient.



Ich hab mich selbst mit der Materie beschäftigt. Wenn Du mal genauer geschaut hättest dann hättest Du auch gesehen das man meine konkrete Frage super beantworten kann (so wie besagter Gast). Der hat übrigens ne gute Note verdient ;-)


----------



## André Uhres (12. Jan 2006)

Naja, ich zitiere mich mal selbst:


			
				Andre_Uhres hat gesagt.:
			
		

> Sets und andere collections die von einer Methode zurückgegeben werden sollten immutable sein
> um die Kapselung zu bewahren.


In DefaultTableModel wäre daher dies wohl besser gewesen:

```
public List getDataVector() {
        return Collections.unmodifiableList(dataVector);
    }
```


----------



## Bleiglanz (12. Jan 2006)

Andre_Uhres hat gesagt.:
			
		

> Naja, ich zitiere mich mal selbst:
> 
> 
> 
> ...


so pauschal ist das etwas gewagt, ich würde sagen dass das von der Anwendung abhängt (und ob das Objekt selbst überhaupt immutable sein soll)?

viele Objekte geben "intelligente" Collections zurück, d.h. solche die auf add / remove usw. einfach entsprechend reagieren (gerade im J2EE Umfeld ist das ziemlich weit verbreitet)


----------



## André Uhres (12. Jan 2006)

Ich weiss nicht was du mit _viele *Objekte* geben "intelligente" Collections zurück_ meinst.
In meinem Zitat meinte ich nicht *Objekte*, sondern den Rückgabewert von *Methoden*.


----------



## Bleiglanz (12. Jan 2006)

eine Methode gehört immer zu einem Objekt? und ob die in einer Methode zurückgelieferte Collection unveränderlich sein soll ist eben eine reine Designfrage


```
Collection<Autor> autoren = buch.getAutoren()
```

es ist eben jetzt eine reine Implementierungsfrage, ob man zu der Liste "autoren" noch einen hinzufügen kann und damit den Zustand des "buch" Objekts verändert...


----------



## Guest (12. Jan 2006)

Andre_Uhres hat gesagt.:
			
		

> Ich weiss nicht was du mit _viele *Objekte* geben "intelligente" Collections zurück_ meinst.
> In meinem Zitat meinte ich nicht *Objekte*, sondern den Rückgabewert von *Methoden*.


Damit meint er einfach spezielle Implementierungen von Collection (als Wrapper, Proxy oder was 
weiss ich noch), die neben der offensichtlichen Funktionalität (add, remove etc.) noch paar andere 
Aktionen im Hintergrund auslösen. Das kann irgendein ausgefallenes Event-Handling sein, 
Transaktionskontrolle, Logging, Wasser kochen  usw.

In einem Extremfall, kannst Du eine komplette Datenbanktabelle als Collection "tarnen". 
Du sagst z.B. add(person) und im Hintergrund wird es durch die Leitung gejagt, in Datenbank 
geschrieben, der Aufruf wird geloggt, eine Message an FBI geschickt etc.


----------



## André Uhres (12. Jan 2006)

Ja gut, nur bleibt dabei die Kapselung auf der Strecke.

EDIT: das ist die Antwort für Bleiglanz.


----------



## Bleiglanz (12. Jan 2006)

Encapsulation != Immutable

wenn Objekt x eine öffentliche Eigenschaft (get/set) vom Typ Collection hat, dann ist das eben so, wer will kann das so machen

wenn man das entsprechend "defensiv" programmiert - so dass äussere Änderungen an der Collection kein Problem verursachen - dann wird die "Kapselung" dadurch überhaupt nicht verletzt ??


----------



## André Uhres (12. Jan 2006)

Bleiglanz hat gesagt.:
			
		

> wenn Objekt x eine öffentliche Eigenschaft (get/set) vom Typ Collection hat, dann ist das eben so, wer will kann das so machen
> wenn man das entsprechend "defensiv" programmiert - so dass äussere Änderungen an der Collection kein Problem verursachen - dann wird die "Kapselung" dadurch überhaupt nicht verletzt ??


Warum entsprechend "defensiv" prorgammieren wenn es mit immutable einfach und sicher geht?


----------



## Bleiglanz (12. Jan 2006)

a) weil immutable unter Umständen nicht praktikabel ist, denk mal an den Speicherverbrauch

b) weil manche Objekte eben einen Zustand haben, den man von aussen verändern kann, das ist die Quintessenz von OO 

c) weil korrektes Programmieren eines immutable Objekts schwierig ist

Beispiel zu c)

ein 


> // in immutable Objekt
> public java.util.Date getDate(){return this.date; // FALSCH }


jetzt MUSS der Programmierer wissen, dass "java.util.Date" mutable ist und also eine Kopie herstellen, d.h. im Endeffekt muss man für jede Property checken, ob das unterliegende Dings selbst einen veränderlichen Zustand hat usw. usf.


----------



## André Uhres (12. Jan 2006)

Jetzt kommen wir glaube ich vom Thema ab.
Es geht ja nur um *Sets und andere collections *:


> Sets und andere collections die von einer Methode zurückgegeben werden sollten immutable sein
> um die Kapselung zu bewahren.


----------

