隐式转换的结果类型必须比AnyRef更具体

时间:2014-10-24 10:38:16

标签: scala

def h(a: AnyRef*) = a.mkString(",")
h: (a: AnyRef*)String

等等

h("1","2")
res: String = 1,2

但是,h(1,2)

error: the result type of an implicit conversion must be more specific than AnyRef
              h(1,2)
                ^
error: the result type of an implicit conversion must be more specific than AnyRef
              h(1,2)
                  ^

至少在Scala 2.11.1和2.11.1中。 要求解决方法。

4 个答案:

答案 0 :(得分:26)

原因是文字1和2的数字类型是Int,它扩展了AnyVal,而Any则扩展了String。另一方面,AnyRef扩展Any,而AnyVal则扩展Int。因此,您可以看到AnyRefAnyRef' s的父级)不会延伸Any。您可以通过以下两种方式之一解决此问题。

第一个是将类型从java.lang.Integer更改为java.lang.Object,如Nate所述。

第二个是对文字1和2使用类型归属,因此它们被认为是AnyRef类型,它扩展了java.lang.Object。另请注意,scala> h(1: java.lang.Integer, 2: java.lang.Integer) res2: String = 1,2 只是{{1}}的别名。因此,使用您的定义,以下内容应该有效:

{{1}}

有关Scala Hierarchy

的更多信息

答案 1 :(得分:19)

您可以使用以下方式重现问题:

val x: AnyRef = 42

以下是介绍此更改的相关pull request on github

基本原理是出于安全原因,明确禁用了一些隐式转换,即如果符合以下条件,则转换从T转到U时将被禁用:

T <: Null

AnyRef <: U

在您的具体情况下,这意味着Int(不是AnyRef)永远不会转换为AnyRef

如果您需要同时接受IntString,则可以考虑接受Any。由于每个scala对象都继承自Any,因此不需要隐式转换。

def h(a: Any*) = a.mkString(",")

答案 2 :(得分:2)

我不认为你想在这里使用AnyRef。我想你想要Any

scala> def h(a: Any*) = a.mkString(",")
h: (a: Any*)String

scala> h(1,2)
res0: String = 1,2

原因是数值5是Int,但AnyRef是java的Object等价。因此,要调用该方法,它需要是一个java.util.Integer。

答案 3 :(得分:2)

通过执行以下操作将变量设置为AnyRef

h(1.asInstanceOf[AnyRef], 2.asInstanceOf[AnyRef])

为什么?

在scala中,并非所有内容都像在Java中那样扩展Object(又名AnyRef)。具体来说,原语会扩展AnyVal,因此,如果您的函数需要AnyRef,则需要强制转换/转换/限制scala变量。

这里有一个很好的讨论:What are the relationships between Any, AnyVal, AnyRef, Object and how do they map when used in Java code?