# List<? implements "Interface"> geht nicht



## Nogge (21. Jan 2009)

Hallo Community,
ich möchte folgendes realisieren, woran mich der Java-Compiler allerdings hindert:

```
public ArrayList<MyInterface> test() {
   ArrayList<TestObject> result = new ArrayList<TestObject>();
	//...
	return result;
}
```
_TestObject_ implementiert hierbei natürlich _MyInterface_. Ich habe bereits folgendes versucht, was ebenfalls zu einem Compiler-Error führte:

```
public ArrayList<? implements MyInterface> test() { ... }
```

Kennt jemand *die* oder eine elegante Lösung für mein Problem?

Vielen Dank, Nogge


----------



## hdi (21. Jan 2009)

Wenn du als Rückgabewert eine ArrayList vom Typ MyInterface erwartest, musst du ihm das auch geben.
Du kannst ihm nicht eine Liste von einer Implementation des Interfaces geben, weil das ja ein Spezialfall 
ist und er erwartet etwas allgemeineres.

Du kannst natürlich trotzdem TestObject-Objekte in eine <MyInterface> parametrisierte Liste stecken.

Also:


```
public ArrayList<MyInterface> test() {
   ArrayList<MyInterface> result = new ArrayList<MyInterface>();
   result.add(new TestObject()); // <-- is ja ok
   return result;
}
```

Wenn du wirklich speziell eine Liste von dieser speziellen Implementation deines Interfaces willst, dann
musst du auch eine ArrayList<TestObject> als Rückgabewert verlangen.


----------



## Capasso (21. Jan 2009)

So müsste es gehen:


```
public ArrayList<? extends MyInterface> test() { ... }
```

siehe auch www.java-forum.org/de/viewtopic.php?t=79263&highlight=


----------



## SvenK (21. Jan 2009)

Nur mal als Anmerkung, da ich das hier schon öfters gesehen habe.
So etwas macht man generell nicht:

```
ArrayList<MyInterface> result = new ArrayList<MyInterface>();
```

Immer gegen Interfaces programmieren. So hat man nämlich die Möglichkeit, die konkrete Implementierung zu tauschen.
Also

```
List<MyInterface> result = new ArrayList<MyInterface>();
```
würde genau so funkionieren wie

```
List<MyInterface> result = new LinkedList<MyInterface>();
```


----------



## Nogge (21. Jan 2009)

Danke an *SvenK *und besonders an *Capasso*!
Ich wollte erst *Capasso* verbal verstümmeln, aber deine Lösung klappt seltsamer Weise. Ein _implements_ anstelle des _extends_ würde meiner Meinung nach mehr Sinn machen. _Extends_ würde ja eigentlich bedeuten, dass ein anderes Interface dieses erweitert/erbt und nicht, dass eine Klasse eben dieses implementieren muss.
Kann mir jmd eine vernünftige Erklärung dazu liefern oder ist das ein Semantikfehler bei der Konstruktion von Java?


----------



## SlaterB (21. Jan 2009)

es gibt 
Class extends Class
Class implements Interface (+ vielleicht noch zusätzlich extends)
Interface extends Interface

-----

nun haben wir 
<? ... T> wobei T Class oder Interface sein kann, 
-> extends passt 2x (oder 2 1/2 x), implements nur 1x bei drei möglichen Fällen, extends gewinnt 

edit:

zudem kann man in eine
List<? extends MyInterface>
auch Objekte vom Typ 'MyInterface2 extends MyInterface' hineinschreiben, es müssen keine richtigen Klassen sein,
falls das nicht klar war


----------



## Ebenius (21. Jan 2009)

Nogge hat gesagt.:
			
		

> Kann mir jmd eine vernünftige Erklärung dazu geben oder ist das ein Semantikfehler bei der Konstruktion von Java?


Es macht in diesem Zusammenhang keinen Unterschied. In jedem Fall ist klar, was gemeint ist. Warum also verschiedene Schlüsselworte?


----------



## Nogge (22. Jan 2009)

Ich habe nun dieses:

```
public List<? extends MyInterface> test() { ... }
```
Seltsam ist jetzt noch folgendes:

```
List<MyInterface> list = test();
```
Diese Zeile ist ungültig ?!? Auch mit einer Implementierung des MyInterfaces will mein Eclipse das nicht akzeptieren. Erst, wenn ich ein Cast mache, zeigt mir meine IDE "nur" noch eine Warnung an, dass es unsicherer Code sei.


----------



## Gelöschtes Mitglied 5909 (22. Jan 2009)

weil du mit extends sagst dass du ein extendedes interface erwartest und nicht das interface selbst

<? extends Foo> --> du musst Foobar extends Foo nehmen
<Foo> --> du kannst Foo oder Foobar nehmen


----------



## SlaterB (22. Jan 2009)

es kann auch das Interface selber sein



```
List<? extends Set> a = null;

        a = new ArrayList<? extends Set>(); // geht übrigens nicht
        a = new ArrayList<Set>(); // geht (1)
        List<HashSet> c = new ArrayList<HashSet>();
        a = c;// geht (2)


        List<Set> b = a; // wäre schlimm wenn das ginge
```

bei der Zuweisung zu b weiß der Compiler nicht, ob das Objekt unter a nun eine ArrayList<Set> ist oder z.B. eine ArrayList<HashSet>

Fall (1) wäre ok, bei Fall (2) wäre das aber fatal, in b könnte man nun auch ein TreeSet einfügen,
und ein get()-Aufruf bei der immer noch vorhandenen Variable c würde zu einer ClassCastException führen


in List a darf man aus ähnlichem Grund generell nichts einfügen, das verbietet der Compiler


----------



## Ebenius (22. Jan 2009)

Nogge, Generics sind nicht so ganz trivial. Lies am besten den gesamten Abschnitt Sun Learning the Java Language: Generics. Die Zeit ist meines Erachtens gut investiert.


----------



## Nogge (22. Jan 2009)

Oben hieß es, dass das ? auch für eine Implementierung gilt. Jetzt wieder nicht? Deswegen meine ich ja, dass es ziemlich verwirrend bzw. sogar falsch von Sun gestaltet wurde. Dann beschreibe ich mal meine Situation genau:
Ich habe einen Client, der auf mehrere Interfaces zugreifen kann. Ein Server implementiert diese Interfaces und stellt dem Client versch. Methoden zur Verfügung, die u.a. eine Liste von Interfaces zurückgeben. Ein Beispiel wäre dann die o.g. _test()_-Methode.
Der Client soll nur die Liste der Interfaces (nur mit get-Methoden, keine set-Methoden) sehen und benutzen, der Server soll eine Liste mit den konkreten Implementierungen (auch mit set-Methoden) sehen und benutzen können. Der Austausch zw. Client und Server soll dann über die Interfaces geschehen.
Mal ein Beispiel in nicht funktionierenden Code, aber die Idee sollte erkennbar sein:

```
[b]SERVER:[/b]
public class Ordering {

private List<Drink> drinks = new ArrayList<Drink>();

public void setCost(float cost, int i) {
		return drinks.get(i).setCost(cost);  // setCost() gibt's nicht im Interface IDrink, nur bei der konkreten Implementierung Drink
}

// für Client-Server-Kommunikation
public List<IDrink> getDrinks() {
		return drinks; // das geht leider nicht
	}
```


```
CLIENT:
List<IDrink> orderedDrinks = getDrinks();
```


----------



## Ebenius (22. Jan 2009)

Es ist nicht falsch gestaltet. Es hat alles Gründe. Um diese zu verstehen, muss man sich damit eingehend beschäftigen. Also erstmal das ganze Tutorial lesen, siehe mein letzter Post. Wenn Du da durch bist, sollte klar sein, warum das Fragezeichen an der einen Stelle geht und an der anderen nicht. Und warum es kein Design-Bug ist.

BTW: Es hat auch Gründe, warum Sun die Generics nicht schon in 1.4 eingebaut haben. Das ganze Konzept steht schon lange, aber es ist nun mal naturbedingt kompliziert.


----------



## SlaterB (22. Jan 2009)

public List<? extends IDrink> getDrinks() { 

wie schon geschrieben wurde (zweite Antwort)

+ beim Client
List<? extends IDrink> orderedDrinks = getDrinks();


----------

