为什么x.toString与(x:Any).toString不同

时间:2014-05-15 08:29:20

标签: scala inheritance overloading read-eval-print-loop

How is ScalaRunTime.stringOf(x) not failing when x.toString fails?开始,

是怎样的
x.toString

不同
(x: Any).toString

另外,怎么样

"" + x

示例REPL会话:

> scala -cp joda-time-2.3.jar
Welcome to Scala version 2.11.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_05).
Type in expressions to have them evaluated.
Type :help for more information.

scala> val dt = new org.joda.time.DateTime
warning: Class org.joda.convert.FromString not found - continuing with a stub.
warning: Class org.joda.convert.ToString not found - continuing with a stub.
warning: Class org.joda.convert.FromString not found - continuing with a stub.
warning: Class org.joda.convert.ToString not found - continuing with a stub.
dt: org.joda.time.DateTime = 2014-05-15T09:27:17.929+01:00

scala> (dt: Any).toString
res0: String = 2014-05-15T09:27:17.929+01:00

scala> "" + dt
res1: String = 2014-05-15T09:27:17.929+01:00

scala> dt.toString
java.lang.AssertionError: assertion failed: org.joda.convert.ToString
at scala.reflect.internal.Symbols$Symbol.info(Symbols.scala:1410)
at scala.reflect.internal.Symbols$TypeSymbol.isNonBottomSubClass(Symbols.scala:3040)
at scala.reflect.internal.AnnotationInfos$AnnotationInfo.matches(AnnotationInfos.scala:305)
at scala.reflect.internal.AnnotationInfos$Annotatable$class.dropOtherAnnotations(AnnotationInfos.scala:68)
at scala.reflect.internal.AnnotationInfos$Annotatable$class.hasAnnotation(AnnotationInfos.scala:53)
at scala.reflect.internal.Symbols$Symbol.hasAnnotation(Symbols.scala:174)
at scala.tools.nsc.typechecker.Infer$class.improves$1(Infer.scala:61)
at scala.tools.nsc.typechecker.Infer$$anonfun$4.apply(Infer.scala:65)
at scala.tools.nsc.typechecker.Infer$$anonfun$4.apply(Infer.scala:65)

1 个答案:

答案 0 :(得分:8)

你的另一个问题的答案清楚地描述了问题,我将再给它一个镜头,并更详细地描述发生了什么。

当您致电dt.toString时,您实际上调用了toString类的DateTime方法,该方法还包含此方法的重载版本。这会导致编译错误,而不是运行时错误,编译器中实际上是一个错误(但它似乎在更新的Scala版本中得到修复,正如其他答案所提到的那样)

对于(dt: Any).toString"" + dt,您不是直接调用toString中的一个重载DateTime方法,而是Any中定义的方法(事实上java.lang.Object#toString)。编译器甚至看不到toString子类的重载DateTime方法 - 因此相应的错误不会产生任何问题。

在运行时,由于动态调度,不会调用Any.toString的实现,而是DateTime.toString。此调度不是由scalac在编译时完成的,而是由JVM在运行时完成的。后者没有超载错误 - 因此不会发生错误。