Wie behebe ich mehrdeutige Methoden, die durch Schnitttypen in Java-Generics verursacht werden?

8

Ich habe kürzlich entdeckt, dass Sie mehrere Typen in einer einzelnen Typparameter-Bindung angeben können (siehe Beispiel). Wie jedes neue Tool habe ich versucht, die Möglichkeiten zu erkunden, wie dies genutzt (und missbraucht) werden kann. Ich habe dieses Beispiel zur Veranschaulichung erstellt.

Im folgenden Beispiel gibt der Compiler mir einen Fehler

  

Versand (neues AlphabetSoup ());

     

Der Methodenversand (Demo.Soup) ist für den Typ Demo mehrdeutig

Ich kann das verstehen, weil beide Methodensignaturen übereinstimmen. Meine Frage ist, wie kann das gelöst werden, ohne die Methoden zu ändern? Wenn ich einen Aufruf zur Soup-Version erzwingen wollte, konnte ich zu Soup runtersinken:

  

Versand ((Suppe) neue AlphabetSoup ())

Aber ich bin mir nicht sicher, wie Sie einen Anruf zu der anderen Version erzwingen würden. Ist es möglich?

%Vor%

- Bearbeiten: Gerade gelernt, dass "mehrere begrenzte Typ Parameter formal als" Intersection-Typen "

bezeichnet werden     
Mark Renouf 02.05.2009, 22:28
quelle

5 Antworten

10

Beachten Sie, dass sich der Fehler nicht auf Generika bezieht, Sie erhalten das gleiche Ergebnis, wenn Sie Schnittstellen verwenden und ein Typ die Schnittmenge ist:

%Vor%

Sie erhalten den gleichen Fehler in "doSomething", der Compiler kann die Mehrdeutigkeit nicht auflösen. Möchten Sie als XX oder als YY interpretieren? Sie müssen es mit einer Besetzung angeben. Aber wenn Sie eine Hierarchie haben, wie "YY erweitert XX" und "XY implementiert YY", kann der Compiler die richtige Methode zum Aufruf ableiten.

    
GClaramunt 02.05.2009 23:48
quelle
6

Der Compiler ist richtig und erspart Ihnen ein Durcheinander.

AlphaBetSoup ist ein Subtyp von Suppe und auch ein Subtyp von HasA, HasB und HasC

Daher passt es für beide Versionen von Dispatch

Da Soup kein Untertyp von HasA, HasB oder HasC ist, kann auch nicht gesagt werden, dass eine Version "spezifischer" ist als die andere.

Daher werden Sie den Fehler korrekt erhalten.

Überladene Methode sollte nicht mehrdeutig sein. Wenn Sie einen Typ haben, der beide Typen mischt und Sie für jede eine Überladung hatten, ändern Sie Ihre Hierarchie oder entfernen Sie eine Überladung. Es ist falsch, Subtyping und Überladung zu verwenden.

    
Uri 02.05.2009 22:43
quelle
2

Lassen Sie mich das mit einem sehr einfachen Programm erklären:

Der Code unter dem dargestellten Code der Methode ist mehrdeutig für den Compilerfehler.

%Vor%

Das Problem ist jetzt offensichtlich: da String sowohl Vergleichbar als auch implementiert Serialisierbar kann der Compiler nicht wissen, welche Methode Sie aufrufen möchten.

Ein einfacher Cast löst das Problem:

ambiguousMethod ((Vergleichbar) "bar");

Ссылка

In unserem Fall verursacht die Methode Versand Probleme. Siehe

%Vor%

und

%Vor%

jetzt, wenn Sie dispatch(new AlphabetSoup()); Compiler aufrufen wäre verwirrt, welche Version des Dispatch sollte aufgerufen werden?

    
AZ_ 24.02.2012 06:40
quelle
1

Beachten Sie, dass Sie kein echtes Problem haben, da die Methoden, die Sie aufrufen möchten, bereits aufgrund der dynamischen Bindung aufgerufen wurden.

Running dispatch((Soup) new AlphabetSoup()); ergibt:

%Vor%

Daher wird die AlphabetSoup -Methode bereits aufgrund von polymorphem Grundverhalten aufgerufen.

    
Yuval Adam 02.05.2009 22:40
quelle
1

Nicht, dass Sie die überladene Methode dispatch beibehalten sollten (ich habe Uri aus diesem Grund hochgestuft), aber Sie können erzwingen, dass die generische Version aufgerufen wird, indem Sie versuchen:

%Vor%

oder rufen Sie die Suppe Version mit:

%Vor%

Der bessere Weg ist jedoch, die überladene Methode dispatch an erster Stelle zu haben.

%Vor%     
Steve Reed 03.05.2009 00:04
quelle

Tags und Links