# Implementierung gegen Interfaces / List, ArrayList, LinkedList



## Sergeant_Pepper (24. Jul 2009)

Hallo,
zur Verwendung der verschiedenen Listen (Vor- und Nachteile) habe ich schon einige Beiträge hier im Forum gelesen. Tlw. wird dann auch darauf verwiesen, dass man vorzugsweise gegen eine Schnittstelle (z.B. List) implementieren soll, anstatt gegen die konkrete Klasse (ArrayList, LinkedList, ...).

Nun schreibe ich gerade ein wrapper-Package zu einem Web Service.

Da habe ich eine Methode wie diese geschrieben:

```
public List<Friend> getFriends()
{
    List<Friend> friends=new LinkedList<Friend>();
    while (..)
    {
         friends.add(...);
    }
...
    return friends;
}
```

Der Aufrufer bekommt also eine List. Das in der Methode eine LinkedList erzeugt wurde, bleibt ihm verborgen.

Aber die Wahl der konkreten Liste kann doch unter Umständen gravierende Auswirkungen haben (z.B. Performance). Das heißt, dass der Programmierer, der getFriends() verwendet, schon wissen sollte, was die Methode konkret tut (nämlich eine LinkedList erzeugen, die tlw. langsamer als eine ArrayList sein kann).

Deshalb würde ich es in diesem Zusammenhang sinnvoller finden, getFriends eine konkrete Liste (z.B. LinkedList) zurückgeben zu lassen. Dann weiß der Anwender, womit er es zu tun hat.

Oder verstehe ich da etwas falsch?


----------



## Noctarius (24. Jul 2009)

Normalerweise benutzt man dann entweder Dependency Injection oder eine Factory Klasse, welche die entsprechende Implementierung (bzw eine Instanz dieser) zurück gibt.


----------



## Sergeant_Pepper (24. Jul 2009)

Dependency Injection ist mir völlig neu, noch nie gehört...

Factories sagen mir etwas. Den Bezug zu meinem Fall sehe ich aber noch nicht. Muss wohl noch etwas lesen... :rtfm:

Danke schon mal...


----------



## faetzminator (24. Jul 2009)

Stell dir vor getFriends() gibt dir eine LinkedList statt einer List zurück. Wenn du nun - z.B. aus Performancegründen - die Implementierung auf eine ArrayList ändern willst, dann ändert sich die Methodensignatur und du bist nicht mehr kompatibel zu den anderen Versionen. Schlimmer noch: Was ist, wenn du eine lib öffentlich verteilst? Dann geht das schon mal gar nicht.


----------



## Gastredner (24. Jul 2009)

Wäre es nicht ein möglicher Ausweg, dem Programmierer zwei Methoden anzubieten? Einer Methode könnte er eine beliebige Liste übergeben, während die zweite nur die erste Methode mit einer neu erzeugten Liste aufruft:

```
public List<Friend> getFriends() {
	return getFriends(new LinkedList<Friend>());
}

public List<Friend> getFriends(List<Friends> list) {
    while (/* Bedingung */) {
		list.add(/* Ein Freund */);
    }
	//...
    return list;
}
```
So hätte dein Gegenüber die freie Wahl, welche Liste er verwenden will.


----------



## Sergeant_Pepper (24. Jul 2009)

@faetzminator:


faetzminator hat gesagt.:


> ... Implementierung auf eine ArrayList ändern willst, dann ändert sich die Methodensignatur und du bist nicht mehr kompatibel zu den anderen Versionen. Schlimmer noch: Was ist, wenn du eine lib öffentlich verteilst? Dann geht das schon mal gar nicht.



Das verstehe ich völlig. Aber wenn man nur eine List zurückgeben will (aus den Gründen, die du genannt hast), sollte man doch wenigstens dokumentieren, welche konkrete List intern verwendet wird, damit jeder weiß, woran er ist.
Oder nicht?


----------



## Marco13 (24. Jul 2009)

Theoretisch könnte der Empfäger auch auf RandomAccess (Java Platform SE 6) testen. Aber das ist IMHO nicht so schön.


----------



## bygones (24. Jul 2009)

Sergeant_Pepper hat gesagt.:


> (nämlich eine LinkedList erzeugen, die tlw. langsamer als eine ArrayList sein kann).


ist sie nur dann wenn man index basiert auf sie zugreift - ergo einfach Collection reintun und gut ist.

Mit DI bzw Factory wäre hier nicht wirklich geholfen, da man auch hier nur mit dem interface als verwender zu tun bekommt.

Wenn es wirklich performancekritisch ist (und das ist in über 90% der fälle nicht) dass man eine ganz bestimmte Implementierung braucht und nur die - dann muss natürliche auch diese verwenden !


----------



## faetzminator (24. Jul 2009)

Kann man, muss man aber nicht. Ist halt Ansichtssache... ich finde Gastredners Idee toll, allerdings noch NPE-sicher:

```
public List<Friend> getFriends() {
    return getFriends(null);
}
 
public List<Friend> getFriends(List<Friend> list) {
    if (list == null) {
        list = new LinkedList<Friend>();
    }
    while (/* Bedingung */) {
        list.add(/* Ein Freund */);
    }
    //...
    return list;
}
```


----------



## Sergeant_Pepper (24. Jul 2009)

zum Vorschlag von Gastredner bzw. faetzminator:

eine der beiden Methoden müsste dann doch einen konkreten Rückgabetyp (LinkedList) haben?


----------



## faetzminator (24. Jul 2009)

Nö. Es geht lediglich darum, dass der Programmierer selbst entscheiden kann, was für eine List er verwendet. Falls dieser in seinem Code LinkedList<...> = ... schreibt, hat er das Prinzip nicht verstanden


----------



## Sergeant_Pepper (24. Jul 2009)

Ja, ich glaub jetzt hab ichs verstanden. Der Aufrufer programmiert:

```
List meineFreunde=getFriends(new LinkedList()); // oder eben new ArrayList();
```
Habe eben auf dem Schlauch gestanden. Tolle Idee!!!

Danke an alle, die Frage ist geklärt.


----------

