1
def testLong(v: Any): Unit = {             
  println(v.getClass)  // print: class java.lang.Long
}
testLong(103L)   // compile passed

from last snippet, it shows that the variable v is class java.lang.Long.And it's a subclass of java.lang.Object.

We also know from the scala Unified types system the AnyRef is equals to java.lang.Object type. But why it compile failed as follows:

def testLong(v: AnyRef): Unit = {             
  println(v.getClass)  
}
testLong(103L)   // compile failed
Adooo
  • 640
  • 6
  • 22
  • You are confusing the `Scala` _compile-time_ **type system** with the `JVM` _runtime_ **class information**. At _compile-time_, Scala only has one Long _(scala.Long)_ which is a subtype of scala.AnyVal _(which is also a subtype of scala.Any)_ but not of scala.AnyRef - that is why your second example fails to compile. However, in the first example, after compilation, in _runtime_ the JVM knows about the primitive Long and the class java.lang.Long _(which is a sub-class, not longer a subtype, of java.lang.Object)_, when you ask for the class of such Long it gets boxed to the class. – Luis Miguel Mejía Suárez Jan 16 '19 at 14:06
  • 2
    Not sure what the compiler error message is supposed to mean exactly, but if you wanted to convert `103L` into a `AnyRef`, you could use `java.lang.Long.valueOf(103L)` or use type ascription and rely on autoboxing: `testLong(103L: java.lang.Long)` – Andrey Tyukin Jan 16 '19 at 14:12
  • @LuisMiguelMejíaSuárez there is a implicit conversion function in the scala.Predef called long2Long, why not scala compiler use this conversion when compile. – Adooo Jan 16 '19 at 14:19
  • @Alex Ah, so your question is why the implicit conversion did not kick in. Let me add an answer that may help you. – Luis Miguel Mejía Suárez Jan 16 '19 at 14:26

1 Answers1

3

Probably the reason why the implicit conversion was not used in the second example is because this:

// val l: AnyRef = 10L
// error: the result type of an implicit conversion must be more specific than AnyRef.

This answer may explain welll why this happens.

However, you can re-write your method for make it work using an implicit evidence.

def testLong[T](v: T)(implicit ev: T => AnyRef): Unit = {             
  println(v.getClass)
}

testLong(10L)
// class java.lang.Long

Curious enough, if you make the method specific to Long only, the printed class changes.

def testLong(v: Long)(implicit ev: Long => AnyRef): Unit = {             
  println(v.getClass)
}

 testLong(10L)
// long