Scala 2.7.7编译器/解释器中的虚假模糊参考错误? [英] Spurious ambiguous reference error in Scala 2.7.7 compiler/interpreter?

查看:319
本文介绍了Scala 2.7.7编译器/解释器中的虚假模糊参考错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

任何人都可以解释下面的编译错误?有趣的是,如果我将 get()方法的返回类型更改为 String ,代码编译就好了。注意, thenReturn 方法有两个重载:一个一元方法和一个varargs方法,至少需要一个参数。在我看来,如果调用在这里是不明确的,那么它总是不明确的。



更重要的是,有没有办法解决歧义?

  import org.scalatest.mock.MockitoSugar 
import org.mockito.Mockito._

trait Thing {
def get():java.lang.Object
}

new MockitoSugar {
val t = mock [Thing]

when(t.get())。thenReturn(a)
}




错误:对重载定义的模糊引用,
两种方法thenReturn in trait类型为

的正在进行的连接java.lang.Object,java.lang.Object *)org.mockito。 stubbing.OngoingStubbing [java.lang.Object]
和方法thenReturn in trait类型为
(java.lang.Object)的进行中的Stubbing org.mockito.stubbing.OngoingStubbing [java.lang.Object]
匹配参数类型(java.lang.String)
when(t.get())。thenReturn(a)



解决方案

好吧,这是不明确的。我假设Java语义允许它,并且它可能值得一个票,要求在Scala中应用Java语义。



歧义的来源是这样的:vararg参数可以接收任何数量的参数,包括0.因此,当你写 thenReturn(a)时,是否意味着调用 thenReturn 它接收一个参数,或者你的意思是调用 thenReturn ,接收一个对象加一个vararg,传递0个参数到vararg?



现在,这种事情发生了,Scala试图找到哪个方法是更具体。任何对细节感兴趣的人都应该在Scala的规范中查找,但下面是在这种特殊情况下会发生什么的解释:

 对象t {
def f(x:AnyRef)= 1 // A
def f(x:AnyRef,xs:AnyRef *)= 2 // B
}
f(foo)/ code>




< $ c>,A和B
都适用。哪一个更多
具体?




  • 可以使用(AnyRef)的参数调用B, A是特定于B的

  • 可以使用类型(AnyRef,
    Seq [AnyRef])的参数调用A
    感谢tuple
    转换, Tuple2 [AnyRef,
    Seq [AnyRef]]
    符合 AnyRef 。所以
    B和A一样具体。因为两个都是
    作为其他的特定,所以
    对f的引用是不明确的。


对于元组转换的东西,它是Scala最隐蔽的语法糖之一。如果您拨打 f(a,b),其中 a b A B ,并且没有 f 接受(A,B)但有一个 f (Tuple2(A,B)),则参数(a,b)将被转换为元组。



例如:

  scala> def f(t:Tuple2 [Int,Int])= t._1 + t._2 
f:(t:(Int,Int))Int

scala> f(1,2)
res0:Int = 3

现在没有元组当 thenReturn(a)被调用时,转换将进行。这不是问题。问题是,考虑到元组转换是可能的, thenReturn 的版本更具体,因为传递给一个的任何参数也可以传递给另一个。 p>

Can anyone explain the compile error below? Interestingly, if I change the return type of the get() method to String, the code compiles just fine. Note that the thenReturn method has two overloads: a unary method and a varargs method that takes at least one argument. It seems to me that if the invocation is ambiguous here, then it would always be ambiguous.

More importantly, is there any way to resolve the ambiguity?

import org.scalatest.mock.MockitoSugar
import org.mockito.Mockito._

trait Thing { 
   def get(): java.lang.Object 
}

new MockitoSugar {   
   val t = mock[Thing]  

   when(t.get()).thenReturn("a")  
}

error: ambiguous reference to overloaded definition, both method thenReturn in trait OngoingStubbing of type
java.lang.Object,java.lang.Object*)org.mockito.stubbing.OngoingStubbing[java.lang.Object] and method thenReturn in trait OngoingStubbing of type (java.lang.Object)org.mockito.stubbing.OngoingStubbing[java.lang.Object] match argument types (java.lang.String) when(t.get()).thenReturn("a")

解决方案

Well, it is ambiguous. I suppose Java semantics allow for it, and it might merit a ticket asking for Java semantics to be applied in Scala.

The source of the ambiguitity is this: a vararg parameter may receive any number of arguments, including 0. So, when you write thenReturn("a"), do you mean to call the thenReturn which receives a single argument, or do you mean to call the thenReturn that receives one object plus a vararg, passing 0 arguments to the vararg?

Now, what this kind of thing happens, Scala tries to find which method is "more specific". Anyone interested in the details should look up that in Scala's specification, but here is the explanation of what happens in this particular case:

object t {
  def f(x: AnyRef) = 1 // A
  def f(x: AnyRef, xs: AnyRef*) = 2 // B
}

if you call f("foo"), both A and B are applicable. Which one is more specific?

  • it is possible to call B with parameters of type (AnyRef), so A is as specific as B.
  • it is possible to call A with parameters of type (AnyRef, Seq[AnyRef]) thanks to tuple conversion, Tuple2[AnyRef, Seq[AnyRef]] conforms to AnyRef. So B is as specific as A. Since both are as specific as the other, the reference to f is ambiguous.

As to the "tuple conversion" thing, it is one of the most obscure syntactic sugars of Scala. If you make a call f(a, b), where a and b have types A and B, and there is no f accepting (A, B) but there is an f which accepts (Tuple2(A, B)), then the parameters (a, b) will be converted into a tuple.

For example:

scala> def f(t: Tuple2[Int, Int]) = t._1 + t._2
f: (t: (Int, Int))Int

scala> f(1,2)
res0: Int = 3

Now, there is no tuple conversion going on when thenReturn("a") is called. That is not the problem. The problem is that, given that tuple conversion is possible, neither version of thenReturn is more specific, because any parameter passed to one could be passed to the other as well.

这篇关于Scala 2.7.7编译器/解释器中的虚假模糊参考错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆