Java-Generika: Illegale Vorwärtsreferenz

8

Gegeben eine generische Schnittstelle

%Vor%

Ich möchte eine Implementierung schreiben, die erfordert, dass A eine Unterklasse von B ist. Also möchte ich

machen %Vor%

oder

%Vor%

Aber die einzige Lösung scheint zu funktionieren:

%Vor%

was ziemlich hässlich ist, weil es die Reihenfolge der generischen Parameter umkehrt.
Gibt es Lösungen oder Problemumgehungen für dieses Problem?

    
Cephalopod 07.01.2011, 17:52
quelle

3 Antworten

5

Da dies in Java nicht möglich ist, denken Sie an Bar<B, A extends B> anders.

Wenn Sie eine Variable für Bar deklarieren, geben Sie zuerst die Elternklasse und dann die Kindklasse an. So funktioniert Bar . Denk nicht daran, dass du rückwärts liegst - denke daran, dass du vorwärts bist. Der Elternteil sollte natürlich vor dem Kind angegeben werden. Diese zusätzliche Beziehung, die Sie hinzugefügt haben, ist die Ursache für die Parameterreihenfolge und nicht für die zugrunde liegende Schnittstelle.

    
Erick Robertson 07.01.2011, 18:25
quelle
1

Nachdem ich diese Frage gesehen hatte, versuchte ich ein paar verschiedene Techniken auszuprobieren, von denen ich dachte, dass sie funktionieren könnten. Erstellen Sie zum Beispiel eine generische Schnittstelle ISuper<B,A extends B> und dann Bar<A,B> implements ISuper<B,A> (und eine ähnliche Technik mit einer Unterklasse und erweitert statt implementiert), aber dies führt nur zu einem Typfehler, Bar.java:1: type parameter A is not within its bound . Ebenso habe ich versucht, eine Methode private <A extends B> Bar<A,B> foo() { return this; }; zu erstellen und sie vom Konstruktor aus aufzurufen, aber das führt nur zur Fehlermeldung vom Typ "Fun" Bar.java:2: incompatible types found : Bar<A,B> required: Bar<A,B>

Also, ich denke, dass die Antwort leider nein ist. Offensichtlich ist es nicht die Antwort, auf die Sie gehofft haben, aber es scheint, dass die richtige Antwort ist, dass dies nicht möglich ist.

    
Keith Irwin 07.01.2011 20:47
quelle
1

Es wurde bereits darauf hingewiesen, dass es weder eine Lösung noch einen guten Workaround gibt. Hier ist, was ich endlich getan habe. Es funktioniert nur für meinen speziellen Fall, aber Sie können es als eine Inspiration nehmen, wenn Sie auf ähnliche Probleme stoßen. (Es erklärt auch, warum ich auf dieses Problem stieß)

Zuerst gibt es diese Klasse (zeigt nur die relevante Schnittstelle):

%Vor%

Die Foo Schnittstelle ist eigentlich

%Vor%

und die Klasse Bar sollte so funktionieren

%Vor%

Am einfachsten wäre es, die Werte wie folgt zu übertragen: p.setNext((Output) p.getNext()) . Aber das ist schlecht, da es eine Instanz von JustCopyIt<Integer, String> erstellen würde. Das Aufrufen dieses Objekts würde auf mysteriöse Weise irgendwann fehlschlagen, aber nicht an dem Punkt, an dem der eigentliche Fehler auftritt.

Doing class JustCopyIt<Type> implements Processor<Type, Type> würde auch hier nicht funktionieren, weil ich dann Pipe<String, Object> nicht verarbeiten kann.

Also, was ich schließlich getan habe, war die Schnittstelle zu diesem ändern:

%Vor%

Auf diese Weise kann JustCopyIt<List> ein Pipe<ArrayList, Collection> verarbeiten.

Obwohl dies technisch die einzig gültige Lösung zu sein scheint, ist es immer noch schlecht, weil es 1) nur für diesen speziellen Fall funktioniert, 2) dass ich die Schnittstelle ändere (was nicht immer möglich ist) und 3) den Code gemacht habe der anderen Prozessoren hässlich.

Bearbeiten:
Das Lesen von Keiths Antwort inspirierte mich erneut zu einer anderen Lösung:

%Vor%     
Cephalopod 08.01.2011 15:31
quelle

Tags und Links