Skip to content

Commit 701e36a

Browse files
committed
add '_035_mutable_objects' section and update ReadMe file
1 parent 6661c88 commit 701e36a

File tree

4 files changed

+139
-4
lines changed

4 files changed

+139
-4
lines changed

README.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,4 @@ I'm using multiple resources to study and apply what I learn here with examples.
2626
* [GitHub Repository](https://github.com/julian-t/EssentialScala) for this course.
2727
* [Scala 101](https://cognitiveclass.ai/learn/scala/#course2000). Free online course on [Cognitive Class](https://cognitiveclass.ai/).
2828
* [Programming in Scala, Third Edition](https://www.oreilly.com/library/view/programming-in-scala/9780981531687/). A book by Bill Venners, Lex Spoon, and Martin Odersky.
29-
* [Scala for Java Developers: A Practical Primer](https://www.apress.com/us/book/9781484231074). A book by Toby Weston.
30-
#
31-
#### Note:
32-
The order of packages and/or files do not always reflect the natural order of learning these specific topics, but the order I used to learn this piece of information.
29+
* [Scala for Java Developers: A Practical Primer](https://www.apress.com/us/book/9781484231074). A book by Toby Weston.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package _035_mutable_objects
2+
3+
/**
4+
* From Chapter 18 - Mutable Objects
5+
* Programming in Scala, Third Edition
6+
*
7+
* > Mutation and vars usually go hand in hand, but things are not always so clear cut. For instance,
8+
* >> a class might be mutable without defining or inheriting any vars because it forwards method calls to other
9+
* objects that have mutable state.
10+
* >> The reverse is also possible: A class might contain vars and still be purely functional.
11+
* >>> An example would be a class that caches the result of an expensive operation in a field for optimization purposes.
12+
* >>> To pick an example, assume the following unoptimized class Keyed with an expensive operation computeKey:
13+
*/
14+
object _01_MutationAndVars {
15+
16+
class Keyed {
17+
def computeKey: Int = 10 // this will take some time (given that we make an action to compute the value).
18+
}
19+
20+
/** > Provided that computeKey neither reads nor writes any vars, you can make Keyed more efficient by adding a cache:
21+
* ...
22+
* > Using MemoKeyed instead of Keyed can speed things up because the second time the result of the computeKey
23+
* operation is requested, the value stored in the keyCache field can be returned instead of running computeKey once
24+
* again. But except for this speed gain, the behavior of class Keyed and MemoKeyed is exactly the same.
25+
* Consequently, if Keyed is purely functional, then so is MemoKeyed, even though it contains a reassignable variable.
26+
* */
27+
class MemoKeyed extends Keyed {
28+
private var keyCache: Option[Int] = None
29+
override def computeKey: Int = {
30+
if (keyCache.isEmpty) keyCache = Some(super.computeKey)
31+
keyCache.get
32+
}
33+
}
34+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package _035_mutable_objects
2+
3+
/**
4+
* From Chapter 18 - Mutable Objects
5+
* > 18.2 REASSIGNABLE VARIABLES AND PROPERTIES
6+
* Programming in Scala, Third Edition
7+
*
8+
*
9+
*/
10+
object _02_ReassignableVarsAndProperties {
11+
12+
// var hour generates a getter, "hour", and setter, "hour_=", in addition to a reassignable field.
13+
// The field is always marked private[this], which means it can be accessed only from the object that contains it.
14+
// The getter and setter, on the other hand, get the same visibility as the original var.
15+
class Time1 {
16+
var hour = 12
17+
var minute = 0
18+
}
19+
20+
// is equivalent to
21+
class Time2 {
22+
23+
private[this] var h = 12
24+
private[this] var m = 0
25+
26+
def hour: Int = h
27+
28+
def hour_=(x: Int): Unit = h = x
29+
30+
def minute: Int = m
31+
32+
def minute_=(x: Int): Unit = m = x
33+
}
34+
35+
class Time3 {
36+
37+
private[this] var h = 12
38+
private[this] var m = 0
39+
40+
def hour: Int = h
41+
42+
def hour_=(x: Int): Unit = {
43+
require(0 <= x && x < 24)
44+
h = x
45+
}
46+
47+
def minute: Int = m
48+
49+
def minute_=(x: Int): Unit = {
50+
require(0 <= x && x < 60)
51+
m = x
52+
}
53+
}
54+
55+
def main(args: Array[String]): Unit = {
56+
val time1 = new Time1
57+
val time2 = new Time2
58+
val time3 = new Time3
59+
60+
time1.hour = 10
61+
time2.hour = 10
62+
time3.hour = 10 // here we have a check in setter method
63+
64+
println(time1.hour)
65+
println(time2.hour)
66+
println(time3.hour)
67+
}
68+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package _035_mutable_objects
2+
3+
/**
4+
* > It's also possible, and sometimes useful, to define a getter and a setter without an associated field.
5+
* >> For example, the Thermometer class below, which encapsulates a temperature variable that can be read and updated.
6+
* >> Temperatures can be expressed in Celsius or Fahrenheit degrees.
7+
* >> This class allows you to get and set the temperature in either measure.
8+
*/
9+
object _03_GetterAndSetterWithoutField {
10+
11+
class Thermometer {
12+
13+
/**
14+
* > Note that you cannot simply leave off the "= _" initializer in Scala.
15+
* > If you did that, this would declare an abstract variable, not an uninitialized one.
16+
*/
17+
var celsius: Float = _ // default value (0.0)
18+
19+
def fahrenheit: Float = celsius * 9 / 5 + 32
20+
21+
def fahrenheit_=(f: Float): Unit = {
22+
celsius = (f - 32) * 5 / 9
23+
}
24+
25+
override def toString: String = fahrenheit + "F/" + celsius + "C"
26+
}
27+
28+
def main(args: Array[String]): Unit = {
29+
val thermometer = new Thermometer
30+
println(thermometer)
31+
thermometer.fahrenheit = 100
32+
println(thermometer)
33+
thermometer.celsius = 100
34+
println(thermometer)
35+
}
36+
}

0 commit comments

Comments
 (0)