1
+ < h1 > Well, In This Case...</ h1 >
2
+ < table class ="table meta-table table-condensed ">
3
+ < tbody >
4
+ < tr >
5
+ < td class ="header-column "> < strong > Contributed by</ strong > </ td >
6
+ < td > Andrew Phillips</ td >
7
+ </ tr >
8
+ < tr >
9
+ < td > < strong > Source</ strong > </ td >
10
+ < td > < a target ="_blank " href ="https://groups.google.com/d/topic/scala-language/DDpvGcrs3QQ/ "> Didier Dupont </ a > </ td >
11
+ </ tr >
12
+ < tr >
13
+ < td > < strong > First tested with Scala version</ strong > </ td >
14
+ < td > 2.11.2</ td >
15
+ </ tr >
16
+ </ tbody >
17
+ </ table >
18
+ < div class ="code-snippet ">
19
+ < h3 > What is the result of executing the following code?</ h3 >
20
+ < pre class ="prettyprint lang-scala ">
21
+ case class Toy(squeezeMsg: String = this.toString) {
22
+ override def toString = squeezeMsg
23
+ }
24
+ println(Toy("My name is Fido!") == new Toy("My name is Fido!"))
25
+ println(Toy() == new Toy())
26
+ </ pre >
27
+ < ol >
28
+ < li > Fails to compile</ li >
29
+ < li id ="correct-answer "> Prints:
30
+ < pre class ="prettyprint lang-scala ">
31
+ true
32
+ false
33
+ </ pre >
34
+ </ li >
35
+ < li > Prints:
36
+ < pre class ="prettyprint lang-scala ">
37
+ true
38
+ true
39
+ </ pre >
40
+ </ li >
41
+ < li > The first statement prints:
42
+ < pre class ="prettyprint lang-scala ">
43
+ true
44
+ </ pre >
45
+ and the second throws a runtime exception
46
+ </ li >
47
+ </ ol >
48
+ </ div >
49
+ < button id ="show-and-tell " class ="btn btn-primary " href ="# "> Display the correct answer, explanation and comments</ button >
50
+ < div id ="explanation " class ="explanation " style ="display:none ">
51
+ < h3 > Explanation</ h3 >
52
+ < p >
53
+ As per the SLS (§5.3.2), if the elements (i.e. constructor parameters) of
54
+ a case class have default arguments, these are carried over to the
55
+ < tt > apply</ tt > factory method on the companion object that is generated by
56
+ the compiler. Also, when < tt > Toy</ tt > is declared, there is indeed a
57
+ < tt > this</ tt > reference in scope, so the code compiles successfully.
58
+ </ p >
59
+ < p >
60
+ The < tt > this</ tt > in < tt > this.toString</ tt > (the value of the default argument
61
+ for < tt > squeezeMsg</ tt > ) does not refer to the instance of < tt > Toy</ tt > being
62
+ created, however. Instead, it resolves to the instance of the class or object
63
+ in which < tt > Toy</ tt > 's constructor is defined.
64
+ </ p >
65
+ < p >
66
+ When running the example in the REPL, the class or object invoking the
67
+ constructor < tt > new Toy()</ tt > directly is a generated "script object":
68
+ < pre class ="prettyprint lang-scala ">
69
+ scala> println(new Toy())
70
+ $line46.$read$$iw$$iw$@7335aa7c
71
+ </ pre >
72
+ When creating a new < tt > Toy</ tt > instance using the standard factory method
73
+ generated for case classes, however, the class or object invoking < tt > Toy</ tt > 's
74
+ constructor is actually the companion object < tt > Toy</ tt > :
75
+ < pre class ="prettyprint lang-scala ">
76
+ scala> println(Toy())
77
+ Toy
78
+ </ pre >
79
+ </ p >
80
+ < p >
81
+ Since the generated implementation of < tt > equals</ tt > for case classes
82
+ uses the values of the case class's elements (< tt > squeezeMsg</ tt > , in this case)
83
+ to determine equality, the two instances < tt > Toy()</ tt > and < tt > new Toy()</ tt >
84
+ are, thus, < em > not</ em > equal.
85
+ </ p >
86
+ </ div >
0 commit comments