定义一个接受类型的方法:List [_&lt ;: AnyVal]
def foo(x : List[_ <: AnyVal]) = x
尝试使用AnyRef:
foo(List(new Test))
error: type mismatch;
found : Test
required: AnyVal
Note that implicit conversions are not applicable because they are ambiguous:
both method ArrowAssoc in object Predef of type [A](self: A)ArrowAssoc[A]
and method Ensuring in object Predef of type [A](self: A)Ensuring[A]
are possible conversion functions from Test to AnyVal
问题1:在警告消息中,为什么编译器会忽略其他两个&#34;泛化为AnyVal&#34; Predef.scala中定义的隐式转换?
final implicit class StringFormat[A] extends AnyVal
final implicit class any2stringadd[A] extends AnyVal
删除先前的歧义并强制编译器使用ArrowAssoc隐式转换:
foo(List(new Test -> 1))
error: the result type of an implicit conversion must be more specific than AnyVal
问题2:此错误消息暗示什么?令人困惑。 ArrowAssoc类中的方法def -> [B](y: B): Tuple2[A, B] = Tuple2(self, y)
返回一个AnyRef类型的Tuple2。那么,更有用的错误消息可能是found Tuple2 required AnyVal
?
答案 0 :(得分:2)
首先回答你的第二个问题。试试这个:
class Temp
implicit class Arrow[T](a:T) extends Temp{
def -->[B](b:B) = (a,b)
}
def foo(x : List[_ <: Temp]) = x
scala> foo(List(1 --> 2))
res0: List[Temp] = List(Arrow@2e17a321)
这可以按预期工作。它没有抱怨,因为它正在搜索Temp
而不是Tuple2
。
现在介绍歧义:
implicit class OtherTemp[T](a:T) extends Temp{}
foo(List(1 --> 2)) //compile error
它没有抱怨碰撞。所以回答你关于为什么它没有显示AnyRef
的问题是因为:
记得ArrowAssoc
正在调用以获得AnyVal
代表。对于->
,它有一个Tuple2并且正在尝试检索AnyVal
。由于无法检索AnyVal
,因此无法转换为AnyVal
时将其标记为错误。它的真实身份是无关紧要的。
对于第一个问题:
根据我的理解,implicits作为第一搜索基础。因此,一旦发现两个并且存在歧义,它就会退出抱怨。可能这就是为什么它不会尝试使用StringFormat
等。这可以通过重新排序隐式订单在repl上确认
implicit class OtherTemp2[T](a:T) extends Temp{
}
implicit class OtherTemp[T](a:T) extends Temp{
}
foo(List[Temp]("asdf"))
编译器以Arrow
和OtherTemp2
作为冲突投诉。如果您重新订购并再次运行repl,它会根据首先发现的隐式进行投诉。
但我找不到一个证实这一点的官方消息来源。