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

后端 未结 4 526
遇见更好的自我
遇见更好的自我 2020-11-29 09:12

Let

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

and so

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

H

相关标签:
4条回答
  • 2020-11-29 09:42

    The reason is that the numeric type of the literals 1 and 2 is Int which extends AnyVal which, in turn, extends Any. On the other hand String extends AnyRef which, 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.

    The first one is changing the type from AnyRef to Any as described by Nate.

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

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

    More info on Scala Hierarchy

    0 讨论(0)
  • 2020-11-29 09:44

    You can reproduce the issue simply with:

    val x: AnyRef = 42
    

    Here's the relevant pull request on github that introduced the change

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

    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.

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

    def h(a: Any*) = a.mkString(",")
    
    0 讨论(0)
  • 2020-11-29 09:58

    I don't think you want to use AnyRef here. I think you want 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 5 is an Int, but AnyRef is java's Object equivalence. So to invoke that method it would need to be a java.util.Integer.

    0 讨论(0)
  • 2020-11-29 09:59

    Cast your variable to AnyRef by doing something like this:

    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 AnyRef you'll need to cast / convert / restrict your scala variables.

    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?

    0 讨论(0)
提交回复
热议问题