5

von How is ScalaRunTime.stringOf(x) not failing when x.toString fails? auf Folgen, wie istWarum ist x.toString verschieden von (x: Any) .ToString

x.toString 

unterscheidet sich von

(x: Any).toString 

Auch, wie etwa

"" + x 

Beispiel REPL-Sitzung:

> 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) 

Antwort

8

Die Antwort auf Ihre andere Frage beschreibt eindeutig das Problem, ich werde es noch einmal versuchen und ausführlicher beschreiben, was vor sich geht.

Wenn Sie anrufen dt.toString Sie tatsächlich die toString Methode der DateTime Klasse aufrufen, die auch eine überladene Version dieses Verfahrens enthält. Dies führt zu einem Übersetzungsfehler, nicht ein Laufzeitfehler, was tatsächlich ein Fehler in dem Compiler ist (aber es scheint, in einer neueren Scala Version als die andere Antwort erwähnt festgelegt werden)

Im Fall von (dt: Any).toString oder "" + dt Sie rufen nicht direkt eine der überladenen -Methoden in DateTime sondern die in Any (die in Wirklichkeit ist java.lang.Object#toString) definiert ist. Der Compiler sieht nicht einmal die überladene toString Methode der DateTime Unterklasse - daher macht der entsprechende Fehler keine Probleme.

Zur Laufzeit wird wegen der dynamischen Versendung nicht die Implementierung Any.toString aufgerufen, sondern DateTime.toString. Dieser Versand erfolgt nicht zur Laufzeit durch scalac, sondern zur Laufzeit durch die JVM. Letzteres hat keinen Überladungsfehler - daher tritt kein Fehler auf.

+0

Ah, die Unterscheidung von Kompilierung und Laufzeit. Ich verstehe. Vielen Dank. –