Aar*_*rup 10 scala compiler-errors
谁能解释下面的编译错误?有趣的是,如果我将方法的返回类型更改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")
}
Run Code Online (Sandbox Code Playgroud)
错误:对重载定义的模糊引用,两个方法然后返回特征类型
java.lang.Object,java.lang.Object*)org.mockito.stubbing.OngoingStubbing [java.lang.Object]和方法返回特征OngoingStubbing的特征OngoingStubbing type(java.lang.Object)org.mockito.stubbing.OngoingStubbing [java.lang.Object]匹配参数类型(java.lang.String)when(t.get()).thenReturn("a")
Dan*_*ral 10
嗯,这是模棱两可的.我认为Java语义允许它,并且它可能值得一张要求在Scala中应用Java语义的票证.
ambiguitity的来源是这样的:一个vararg参数可以接收任意数量的参数,包括0.所以,当你写的时候thenReturn("a"),你的意思是调用thenReturn哪个接收一个参数,或者你的意思是调用thenReturn它接收一个对象加上一个vararg,将0个参数传递给vararg?
现在,发生了类似的事情,Scala试图找出哪种方法"更具体".任何对细节感兴趣的人都应该在Scala的规范中查找,但这里是对这种特殊情况下发生的事情的解释:
object t {
def f(x: AnyRef) = 1 // A
def f(x: AnyRef, xs: AnyRef*) = 2 // B
}
Run Code Online (Sandbox Code Playgroud)
如果你打电话
f("foo"),A和B都适用.哪一个更具体?
- 可以使用类型参数调用B
(AnyRef),因此A与B一样具体.(AnyRef, Seq[AnyRef])由于元组转换,可以使用类型参数调用A ,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
Run Code Online (Sandbox Code Playgroud)
现在,thenReturn("a")调用时没有元组转换.那不是问题.问题是,鉴于元组转换是可能的,两个版本都不thenReturn是更具体,因为传递给一个的任何参数也可以传递给另一个.
小智 7
在Mockito的特定情况下,可以使用为void方法设计的备用API方法:
doReturn("a").when(t).get()
Run Code Online (Sandbox Code Playgroud)
Clunky,但它必须这样做,因为Martin等人似乎不会为了支持Java的varargs而牺牲Scala.
好吧,我想出了如何解决歧义(回想起来似乎有点明显):
when(t.get()).thenReturn("a", Array[Object](): _*)
Run Code Online (Sandbox Code Playgroud)
正如安德烈亚斯所指出的,如果模糊方法需要空引用而不是空数组,则可以使用类似的方法
v.overloadedMethod(arg0, null.asInstanceOf[Array[Object]]: _*)
Run Code Online (Sandbox Code Playgroud)
解决歧义.