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 werdenBeachten 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.
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.
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?
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:
Daher wird die AlphabetSoup
-Methode bereits aufgrund von polymorphem Grundverhalten aufgerufen.
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:
oder rufen Sie die Suppe Version mit:
%Vor% Der bessere Weg ist jedoch, die überladene Methode dispatch
an erster Stelle zu haben.