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?
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.
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.
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
und die Klasse Bar
sollte so funktionieren
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:
Tags und Links java generics syntax-error