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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26546299/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 06:38:43  来源:igfitidea点击:

Result type of an implicit conversion must be more specific than AnyRef

scala

提问by elm

Let

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

and so

所以

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

However, h(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)
                  ^

This is at least in Scala 2.11.1 and 2.11.1. To ask on a workaround.

这至少在 Scala 2.11.1 和 2.11.1 中是这样。询问解决方法。

采纳答案by Gabriele Petronella

You can reproduce the issue simply with:

您可以简单地重现该问题:

val x: AnyRef = 42

Here's the relevant pull request on githubthat introduced the change

这是介绍更改的github上的相关拉取请求

The rationale is that for security reasons some implicit conversions are explicitly disabled, namely when the conversion goes from Tto Uis disabled if:

其基本原理是出于安全原因,某些隐式转换被显式禁用,即当转换从T到时U被禁用,如果:

T <: Null

or

或者

AnyRef <: U

In your specific case, this means that an Int(which is not an AnyRef) will never be converted to AnyRef.

在您的特定情况下,这意味着 an Int(不是 an AnyRef)永远不会转换为AnyRef.

If you need to accept both Intand String, you can consider accepting Anyinstead. Since every scala object inherits from Any, there's no implicit conversion needed.

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

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

回答by lambdista

The reason is that the numeric type of the literals 1 and 2 is Intwhich extends AnyValwhich, in turn, extends Any. On the other hand Stringextends AnyRefwhich, in turn, extends Any. So as you can see AnyVal(Int's parent) does not extend AnyRef. You can solve this in one of two ways.

原因是文字 1 和 2 的数字类型是Int扩展AnyVal,而扩展又是扩展Any。另一方面,Stringextends AnyRef,反过来, extends Any。因此,如您所见,AnyVal(Int的父级) 不会扩展AnyRef. 您可以通过以下两种方式之一解决此问题。

The first one is changing the type from AnyRefto Anyas described by Nate.

第一个是按照 Nate 的描述将类型从AnyRef更改Any为 。

The second one is using a type ascription for the literals 1 and 2 so that they are considered of type java.lang.Integerwhich extends java.lang.Object. Note also that AnyRefis just an alias for java.lang.Object. So, using your definition the following should work:

第二个是对文字 1 和 2 使用类型归属,以便将它们视为java.lang.Integer扩展的类型java.lang.Object。另请注意,这AnyRef只是java.lang.Object. 因此,使用您的定义,以下内容应该有效:

scala> h(1: java.lang.Integer, 2: java.lang.Integer)
res2: String = 1,2

More info on Scala Hierarchy

有关Scala 层次结构的更多信息

回答by Nate

I don't think you want to use AnyRefhere. I think you want Any.

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

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

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

The reason is that the numeric value 5is an Int, but AnyRefis java's Objectequivalence. So to invoke that method it would need to be a java.util.Integer.

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

回答by Matthew

Cast your variable to AnyRefby doing something like this:

AnyRef通过执行以下操作将您的变量转换为:

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

Why?

为什么?

In scala not everything extends Object(aka AnyRef) in the way that it would in java. Specifically primitives extend AnyVal, so if your function requires an AnyRefyou'll need to cast / convert / restrict your scala variables.

在 scala 中,并非所有东西都像在 java 中那样扩展Object(又名AnyRef)。特别是原语扩展AnyVal,所以如果你的函数需要一个AnyRef你需要强制转换/转换/限制你的scala变量。

There's a good discussion here: What are the relationships between Any, AnyVal, AnyRef, Object and how do they map when used in Java code?

这里有一个很好的讨论:Any、AnyVal、AnyRef、Object 之间的关系是什么以及它们在 Java 代码中使用时如何映射?