@@ -97,26 +97,100 @@ p.vocation = "Musician"
9797{% endtab %}
9898{% endtabs %}
9999
100- ### Fields and methods
100+ ### ` val ` makes fields read-only
101101
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:
105171
106172{% tabs method class=tabs-scala-version %}
107173{% tab 'Scala 2' %}
108174
109175``` scala
110176class Person (var firstName : String , var lastName : String ) {
111-
112177 println(" initialization begins" )
178+ // 'public' access by default
113179 val fullName = firstName + " " + lastName
114180
181+ // a private field
182+ private val HOME = System .getProperty(" user.home" )
183+
115184 // a class method
116185 def printFullName : Unit =
117186 // access the `fullName` field, which is created above
118187 println(fullName)
119188
189+ def printHome : Unit = println(s " HOME = $HOME" )
190+
191+ // an overridden method
192+ override def toString (): String = fullName
193+
120194 printFullName
121195 println(" initialization ends" )
122196}
@@ -128,15 +202,23 @@ class Person(var firstName: String, var lastName: String) {
128202
129203``` scala
130204class Person (var firstName : String , var lastName : String ):
131-
132205 println(" initialization begins" )
206+ // 'public' access by default
133207 val fullName = firstName + " " + lastName
134208
209+ // a private field
210+ private val HOME = System .getProperty(" user.home" )
211+
135212 // a class method
136213 def printFullName : Unit =
137214 // access the `fullName` field, which is created above
138215 println(fullName)
139216
217+ def printHome : Unit = println(s " HOME = $HOME" )
218+
219+ // an overridden method
220+ override def toString (): String = fullName
221+
140222 printFullName
141223 println(" initialization ends" )
142224```
@@ -153,10 +235,16 @@ scala> val john = new Person("John", "Doe")
153235initialization begins
154236John Doe
155237initialization ends
156- val john : Person = Person @ 55d8f6bb
238+ val john : Person = John Doe
157239
158240scala> john.printFullName
159241John Doe
242+
243+ scala> john.printHome
244+ HOME = / Users / al
245+
246+ scala> println(john)
247+ John Doe
160248````
161249{% endtab %}
162250{% tab 'Scala 3' %}
@@ -165,10 +253,16 @@ scala> val john = Person("John", "Doe")
165253initialization begins
166254John Doe
167255initialization ends
168- val john : Person = Person @ 55d8f6bb
256+ val john : Person = John Doe
169257
170258scala> john.printFullName
171259John Doe
260+
261+ scala> john.printHome
262+ HOME = / Users / al
263+
264+ scala> println(john)
265+ John Doe
172266````
173267{% endtab %}
174268{% endtabs %}
@@ -788,6 +882,83 @@ val d = IrishSetter("Big Red") // "Big Red is a Dog"
788882{% endtab %}
789883{% endtabs %}
790884
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+
791962This is just a taste of what you can accomplish with traits.
792963For more details, see the remainder of these modeling lessons.
793964
0 commit comments