【问题标题】:Result type of an implicit conversion must be more specific than AnyRef隐式转换的结果类型必须比 AnyRef 更具体
【发布时间】:2014-10-24 10:38:15
【问题描述】:

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 中是这样。 询问解决方法。

【问题讨论】:

  • scala 2.10.X 上的 scala repl 给出了更有意义的响应:error: type mismatch; found : Int(1) required: AnyRef Note: an implicit exists from scala.Int => java.lang.Integer, but methods inherited from Object are rendered ambiguous. This is to avoid a blanket implicit which would convert any scala.Int to any AnyRef. You may wish to use a type ascription: x: java.lang.Integer. h(1,2)
  • 顺便用val x: AnyRef = 42复现问题

标签: scala


【解决方案1】:

原因是文字 1 和 2 的数字类型是 Int,它扩展了 AnyVal,而后者又扩展了 Any。另一方面,String 扩展了 AnyRef,而后者又扩展了 Any。如您所见,AnyValInt 的父级)没有扩展 AnyRef。您可以通过以下两种方式之一解决此问题。

第一个是将类型从 AnyRef 更改为 Any,如 Nate 所述。

第二个是对文字 1 和 2 使用类型归属,以便将它们视为扩展 java.lang.Object 的类型 java.lang.Integer。还要注意AnyRef 只是java.lang.Object 的别名。因此,使用您的定义应该可以:

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

更多信息Scala Hierarchy

【讨论】:

    【解决方案2】:

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

    val x: AnyRef = 42
    

    这是引入更改的相关pull request on github

    基本原理是出于安全原因,某些隐式转换被显式禁用,即从TU 的转换在以下情况下被禁用:

    T <: Null
    

    AnyRef <: U
    

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

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

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

    【讨论】:

    • 如果 h 是像 h(ArrayList x) 这样的 java 函数怎么办?
    【解决方案3】:

    通过执行以下操作将您的变量转换为 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?

    【讨论】:

      【解决方案4】:

      我认为您不想在这里使用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。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-10-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-09
        • 2011-09-26
        相关资源
        最近更新 更多