@@ -97,26 +97,100 @@ p.vocation = "Musician"
97
97
{% endtab %}
98
98
{% endtabs %}
99
99
100
- ### Fields and methods
100
+ ### ` val ` makes fields read-only
101
101
102
- Classes can also have methods and additional fields that are not part of constructors.
103
- They are defined in the body of the class.
104
- The body is initialized as part of the default constructor:
102
+ In that first example both fields were defined as ` var ` fields:
103
+
104
+ {% tabs class_val_fields_1 %}
105
+ {% tab 'Scala 2 and 3' %}
106
+ ``` scala
107
+ class Person (var name : String , var vocation : String )
108
+ ```
109
+ {% endtab %}
110
+ {% endtabs %}
111
+
112
+ That makes those fields mutable. You can also define them as ` val ` fields, which makes them immutable:
113
+
114
+ {% tabs class_val_fields_2 %}
115
+ {% tab 'Scala 2 and 3' %}
116
+ ``` scala
117
+ class Person (val name : String , val vocation : String )
118
+ // --- ---
119
+ ```
120
+ {% endtab %}
121
+ {% endtabs %}
122
+
123
+ If you now try to change the name of a ` Person ` instance, you’ll see an error:
124
+
125
+ {% tabs class_val_fields_3 class=tabs-scala-version %}
126
+ {% tab 'Scala 2' %}
127
+ ``` scala
128
+ scala> class Person (val name : String , val vocation : String )
129
+ class Person
130
+
131
+ scala> val p = new Person (" Robert Allen Zimmerman" , " Harmonica Player" )
132
+ val p : Person = Person @ 1c58d7be
133
+
134
+ scala> p.name = " Bob Dylan"
135
+ ^
136
+ error: reassignment to val
137
+ ```
138
+ {% endtab %}
139
+ {% tab 'Scala 3' %}
140
+ ``` scala
141
+ scala> class Person (val name : String , val vocation : String )
142
+ // defined class Person
143
+
144
+ scala> val p = Person (" Robert Allen Zimmerman" , " Harmonica Player" )
145
+ val p : Person = Person @ 779228dc
146
+
147
+ scala> p.name = " Bob Dylan"
148
+ -- [E052 ] Type Error : ----------------------------------------------------------
149
+ 1 | p.name = " Bob Dylan"
150
+ |^^^^^^^^^^^^^^^^^^^^
151
+ | Reassignment to val name
152
+ |
153
+ | longer explanation available when compiling with `-explain`
154
+ 1 error found
155
+ ```
156
+ {% endtab %}
157
+ {% endtabs %}
158
+
159
+ ### Class constructors
160
+
161
+ In Scala, the primary constructor of a class is a combination of:
162
+
163
+ - The constructor parameters
164
+ - Methods that are called in the body of the class
165
+ - Statements and expressions that are executed in the body of the class
166
+
167
+ Defining parameters in the primary constructor automatically creates fields in the class, and fields declared in the body
168
+ of a Scala class are handled in a manner similar to Java; they are assigned when the class is first instantiated.
169
+
170
+ This ` Person ` class demonstrates several of the things you can do inside the body of a class:
105
171
106
172
{% tabs method class=tabs-scala-version %}
107
173
{% tab 'Scala 2' %}
108
174
109
175
``` scala
110
176
class Person (var firstName : String , var lastName : String ) {
111
-
112
177
println(" initialization begins" )
178
+ // 'public' access by default
113
179
val fullName = firstName + " " + lastName
114
180
181
+ // a private field
182
+ private val HOME = System .getProperty(" user.home" )
183
+
115
184
// a class method
116
185
def printFullName : Unit =
117
186
// access the `fullName` field, which is created above
118
187
println(fullName)
119
188
189
+ def printHome : Unit = println(s " HOME = $HOME" )
190
+
191
+ // an overridden method
192
+ override def toString (): String = fullName
193
+
120
194
printFullName
121
195
println(" initialization ends" )
122
196
}
@@ -128,15 +202,23 @@ class Person(var firstName: String, var lastName: String) {
128
202
129
203
``` scala
130
204
class Person (var firstName : String , var lastName : String ):
131
-
132
205
println(" initialization begins" )
206
+ // 'public' access by default
133
207
val fullName = firstName + " " + lastName
134
208
209
+ // a private field
210
+ private val HOME = System .getProperty(" user.home" )
211
+
135
212
// a class method
136
213
def printFullName : Unit =
137
214
// access the `fullName` field, which is created above
138
215
println(fullName)
139
216
217
+ def printHome : Unit = println(s " HOME = $HOME" )
218
+
219
+ // an overridden method
220
+ override def toString (): String = fullName
221
+
140
222
printFullName
141
223
println(" initialization ends" )
142
224
```
@@ -153,10 +235,16 @@ scala> val john = new Person("John", "Doe")
153
235
initialization begins
154
236
John Doe
155
237
initialization ends
156
- val john : Person = Person @ 55d8f6bb
238
+ val john : Person = John Doe
157
239
158
240
scala> john.printFullName
159
241
John Doe
242
+
243
+ scala> john.printHome
244
+ HOME = / Users / al
245
+
246
+ scala> println(john)
247
+ John Doe
160
248
````
161
249
{% endtab %}
162
250
{% tab 'Scala 3' %}
@@ -165,10 +253,16 @@ scala> val john = Person("John", "Doe")
165
253
initialization begins
166
254
John Doe
167
255
initialization ends
168
- val john : Person = Person @ 55d8f6bb
256
+ val john : Person = John Doe
169
257
170
258
scala> john.printFullName
171
259
John Doe
260
+
261
+ scala> john.printHome
262
+ HOME = / Users / al
263
+
264
+ scala> println(john)
265
+ John Doe
172
266
````
173
267
{% endtab %}
174
268
{% endtabs %}
@@ -788,6 +882,83 @@ val d = IrishSetter("Big Red") // "Big Red is a Dog"
788
882
{% endtab %}
789
883
{% endtabs %}
790
884
885
+ ### Overriding an implemented method
886
+
887
+ A class can also override a method that is defined in a trait. Here is an example:
888
+
889
+ {% tabs traits_6 class=tabs-scala-version %}
890
+ {% tab 'Scala 2' %}
891
+ ``` scala
892
+ class Cat extends HasLegs with HasTail {
893
+ val numLegs = 4
894
+ val tailColor = " Tabby"
895
+ def walk () = println(" I’m not walking" )
896
+ // override 'stop'
897
+ override def stop () = println(" I'm still not walking" )
898
+ }
899
+ ```
900
+ {% endtab %}
901
+ {% tab 'Scala 3' %}
902
+ ``` scala
903
+ class Cat extends HasLegs , HasTail :
904
+ val numLegs = 4
905
+ val tailColor = " Tabby"
906
+ def walk () = println(" I’m not walking" )
907
+ // override 'stop'
908
+ override def stop () = println(" I'm still not walking" )
909
+ ```
910
+ {% endtab %}
911
+ {% endtabs %}
912
+
913
+ The REPL shows how this works:
914
+
915
+ {% tabs traits_7 class=tabs-scala-version %}
916
+ {% tab 'Scala 2' %}
917
+ ``` scala
918
+ scala> val c = new Cat
919
+ val c : Cat = Cat @ 3855b27e
920
+
921
+ scala> c. walk()
922
+ I ’m not walking
923
+
924
+ scala> c.stop()
925
+ I ' m still not walking
926
+ ```
927
+ {% endtab %}
928
+ {% tab 'Scala 3' %}
929
+ ``` scala
930
+ scala> val c = Cat ()
931
+ val c : Cat = Cat @ 539ee811
932
+
933
+ scala> c.walk()
934
+ I ’m not walking
935
+
936
+ scala> c.stop()
937
+ I ' m still not walking
938
+ ```
939
+ {% endtab %}
940
+ {% endtabs %}
941
+
942
+ You can also override a method when creating an instance of a class:
943
+
944
+ {% tabs traits_8 class=tabs-scala-version %}
945
+ {% tab 'Scala 2' %}
946
+ ``` scala
947
+ val c = new Cat {
948
+ override def walk () = println(" Run" )
949
+ override def stop () = println(" I will continue to run" )
950
+ }
951
+ ```
952
+ {% endtab %}
953
+ {% tab 'Scala 3' %}
954
+ ``` scala
955
+ val c = new Cat :
956
+ override def walk () = println(" Run" )
957
+ override def stop () = println(" I will continue to run" )
958
+ ```
959
+ {% endtab %}
960
+ {% endtabs %}
961
+
791
962
This is just a taste of what you can accomplish with traits.
792
963
For more details, see the remainder of these modeling lessons.
793
964
0 commit comments