Falscher mehrdeutiger Referenzfehler in Scala 2.7.7 Compiler / Interpreter?

7

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")

    
Aaron Novstrup 29.01.2010, 01:08
quelle

5 Antworten

9

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]] entspricht AnyRef . 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.

    
Daniel C. Sobral 29.01.2010, 11:27
quelle
6

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.

    
Aaron Novstrup 29.01.2010 01:40
quelle
6

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.

    
Coda Hale 17.02.2010 03:14
quelle
4

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](): _* .

    
Randall Schulz 29.01.2010 15:38
quelle
3

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)

    
Andreas 31.01.2010 17:35
quelle

Tags und Links