5

Tiếp theo từ How is ScalaRunTime.stringOf(x) not failing when x.toString fails?, làm thế nào làTại sao x.toString khác với (x: Bất kỳ) ToString

x.toString 

khác nhau từ

(x: Any).toString 

Ngoài ra, làm thế nào về

"" + x 

Phiên REPL ví dụ:

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

Trả lời

8

Câu trả lời cho câu hỏi khác của bạn mô tả rõ vấn đề, tôi sẽ cung cấp cho nó một ảnh khác và mô tả chi tiết hơn những gì đang diễn ra.

Khi bạn gọi dt.toString bạn thực sự gọi phương thức toString của lớp DateTime, cũng chứa phiên bản quá tải của phương pháp này. Điều này dẫn đến lỗi biên dịch, không phải lỗi thời gian chạy, lỗi thực sự là một lỗi trong trình biên dịch (nhưng có vẻ như đã được khắc phục trong phiên bản Scala mới hơn như các câu trả lời khác)

Trong trường hợp (dt: Any).toString hoặc "" + dt bạn không trực tiếp gọi một trong các phương thức quá tải toString trong DateTime nhưng phương thức được xác định trong Any (thực tế là java.lang.Object#toString). Trình biên dịch thậm chí không nhìn thấy phương thức quá tải toString của lớp con DateTime - do đó lỗi tương ứng không gây ra bất kỳ vấn đề nào.

Khi chạy, vì công văn động không thực hiện Any.toString được gọi nhưng DateTime.toString. Công văn này không được thực hiện bởi scalac tại thời gian biên dịch mà bởi JVM khi chạy. Sau này không có lỗi quá tải - do đó không có lỗi xảy ra.

+0

Ah, sự khác biệt về biên dịch và thời gian chạy. Tôi hiểu. Cảm ơn. –

Các vấn đề liên quan