Kann jemand den Kompilierungsfehler unten erklären? Interessanterweise, wenn ich den Rückgabetyp der get()
Methode zu String
ändere, kompiliert der Code einfach gut. Beachten Sie, dass die Methode thenReturn
zwei Überladungen aufweist: eine unäre Methode und eine varargs-Methode, die mindestens ein Argument benötigt. Es scheint mir, wenn die Invokation hier zweideutig ist, dann wäre sie immer mehrdeutig.
Noch wichtiger ist, gibt es eine Möglichkeit, die Mehrdeutigkeit zu lösen?
%Vor%Fehler: mehrdeutiger Verweis auf überladene Definition, beide Methoden thenReturn in Merkmal OngoingStubbing vom Typ
java.lang.Object, java.lang.Object *) org.mockito.stubbing.OngoingStubbing [java.lang.Object] und Methode thereReturn in Merkmal OngoingStubbing des Typs (java.lang.Object) org.mockito.stubbing.OngoingStubbing [java.lang.Object] Match-Argumenttypen (java.lang.String) when (t.get ()). thenReturn ("a")
Nun, es ist mehrdeutig. Ich nehme an, dass die Java-Semantik dies zulässt, und es könnte ein Ticket verdienen, dass die Java-Semantik in Scala angewendet wird.
Die Quelle der Ambiguität ist folgende: Ein Vararg-Parameter kann eine beliebige Anzahl von Argumenten einschließlich 0 erhalten. Wenn Sie also thenReturn("a")
schreiben, wollen Sie thenReturn
aufrufen, das ein einzelnes Argument erhält oder tut Sie wollen das thenReturn
aufrufen, das ein Objekt plus ein vararg erhält, und 0 Argumente an das vararg übergeben?
Nun, was passiert, Scala versucht herauszufinden, welche Methode "spezifischer" ist. Wer sich für die Details interessiert, sollte das in Scalas Spezifikation nachschlagen, aber hier ist die Erklärung, was in diesem speziellen Fall passiert:
%Vor%Wenn Sie
f("foo")
aufrufen, sowohl A als auch B sind anwendbar. Welches ist mehr? Spezifisch?
- es ist möglich, B mit Parametern vom Typ
(AnyRef)
aufzurufen, also A ist so spezifisch wie B.- es ist möglich, A mit Parametern des Typs
(AnyRef, Seq[AnyRef])
dank Tupel aufzurufen Konvertierung,Tuple2[AnyRef, Seq[AnyRef]]
entsprichtAnyRef
. Damit B ist so spezifisch wie A. Da beide sind so spezifisch wie die andere, die Verweis auf f ist mehrdeutig.
Was die "Tupelumwandlung" betrifft, ist es einer der unbekanntesten syntaktischen Zucker von Scala. Wenn Sie f(a, b)
aufrufen, haben a
und b
die Typen A
und B
und es gibt keine f
akzeptiert (A, B)
, aber es gibt f
, die (Tuple2(A, B))
akzeptiert. , dann werden die Parameter (a, b)
in ein Tupel umgewandelt.
Zum Beispiel:
%Vor% Nun wird keine Tupel-Konvertierung mehr ausgeführt, wenn thenReturn("a")
aufgerufen wird. Das ist nicht das Problem. Das Problem ist, dass angesichts der Tatsache, dass eine Tupel-Konvertierung möglich ist, keine der beiden Versionen von thenReturn
spezifischer ist, da alle Parameter, die an einen übergeben werden, auch an den anderen übergeben werden könnten.
Nun, ich habe herausgefunden, wie man die Mehrdeutigkeit auflösen kann (scheint im Rückblick etwas offensichtlich zu sein):
%Vor%Wie Andreas bemerkt hat, können Sie etwas wie
verwenden, wenn die mehrdeutige Methode einen NULL-Verweis und nicht ein leeres Array benötigt %Vor%um die Mehrdeutigkeit zu beheben.
Im speziellen Fall von Mockito ist es möglich, alternative API-Methoden zu verwenden, die für void-Methoden entwickelt wurden:
%Vor% Clunky, aber es wird reichen müssen, da Martin und andere Scala wahrscheinlich nicht kompromittieren, um Javas Varargs zu unterstützen.Wenn Sie sich die APIs für die Standardbibliothek ansehen, wird dieses Problem wie folgt behandelt:
%Vor% Dadurch ist kein Aufruf (mit mindestens einem Thing-Parameter) mehrdeutig ohne zusätzliche Flusen wie Array[Thing](): _*
.
Ich hatte ein ähnliches Problem mit Oval (oval.sf.net) versucht, es ist validate () - Methode zu nennen.
Oval definiert zwei validate () Methoden:
%Vor%Dies von Scala aus versuchen: %Code% erzeugt den folgenden Compilerfehler:
%Vor%Oval benötigt den varargs-Parameter als null, nicht als leeres Array, also habe ich es endlich damit arbeiten lassen:
validator.validate(value)
Tags und Links scala compiler-errors