Overview

The next stop in the Scala journey is classes. Classes are the cornerstone of object oriented programming. In the simplest form, a Scala class looks similar to classes in Java and C++.

Scala Classes 1

In the simplest case, a class will model an entity of the modeled domain. It will expose an API that application code can use. Private fields correspond to the state of the object modelled after a class. The following snippet shows how to create a class that has a private field named value, a getter function and a modifier function.

class MyClass {
    
    private var value = 0.0
    
    def increment() = value += 1.0
    def getValue = value
    
}
defined class MyClass

Specific instances can be used by using the new operator. For example, the following creates an instance of MyClass.

val inst1 = new MyClass
inst1: MyClass = ammonite.$sess.cmd5$Helper$MyClass@5743442d
println(inst1.getValue)
0.0
inst1.increment()
println(inst1.getValue)
1.0

Getters and setters are frequently used to change properties of a class. Alghtough, such methods allow for every client of the class to modify the state of the class, they are the preferred way of doing so. This is because they allow us to control how the change of the class state is done. Scala can generate getters and setters for us for every private field of our class [1].

class MyClass2{
    var value = 0.0
}
defined class MyClass2
val inst2 = new MyClass2
inst2: MyClass2 = ammonite.$sess.cmd10$Helper$MyClass2@52cac8e8
print(inst2.value)
0.0
inst2.value = 10.0
print(inst2.value)
10.0

Remark

In Scala, the getters and setters are not named as getXxx and setXxx. Instead, they take the name of the private variable [1]. Note also that if we don't want the getters and setters to be generated then we should declare this field with private[this].


Although Scala defines getters and setters for us, we can redefine the getter and setter methods generated for us [1]. This is shown below

class MyClass3{
    var myValue = 0.0
    
    def value = myValue
    def value_=(newValue: Double) : Unit = {
        // we can control how the state is
        // changed here
    
        if(newValue > 10.0) myValue = 5
        else myValue = newValue
    }
}
defined class MyClass3
val inst3 = new MyClass3
inst3: MyClass3 = ammonite.$sess.cmd0$Helper$MyClass3@1384d29d
println(inst3.value)
0.0
inst3.value = 3.0
println(inst3.value)
3.0
inst3.value = 50
println(inst3.value)
5.0

Here are a few points regarding setters and getters to remember [1]

  • If the field is private then both functions are private
  • If the field is declared using val, then only a getter is generated
  • If no getter or setter is needed for the field, declare this as private[this]
  • We cannot have a write-only field i.e a field with a setter and no getter

Finally note that, in contrast to Java, a class source file in Scala can contain multiple classes. Moreover, we do not need to declare a Scala class as public [1].

private[this]

Every instance of a class has access to the private members of instances of the same class. For example, the following is legal

class ShowMeMsg{
    private var msg = "Nothing"
    
    def setMsg(newMesg: String) : Unit = msg=newMesg
    
    def isMessage(other: ShowMeMsg) = {
        if(other.msg == this.msg){
            println("It is message")
        }
    }
}
defined class ShowMeMsg
var msg1 = new ShowMeMsg
msg1.setMsg("ONE")
var msg2 = new ShowMeMsg
msg2.setMsg("ONE")
msg1.isMessage(msg2)
It is message

Thus, msg1 has access to the field of msg2. This means that if the field is of var type mgs1 could potentially change it. Certainly, this is not a desired scenario most of the times. We can prevent this sort of situation by using the private[this] qualifier. This allows an even more severe access restriction [1]. This is shown below.

class ShowMeMsg_2{
    private[this] var msg = "Nothing"
    
    def setMsg(newMesg: String) : Unit = msg=newMesg
    
    def isMessage(other: ShowMeMsg) = {
        if(other.msg == this.msg){
            println("It is message")
        }
    }
}
cmd41.sc:7: variable msg in class ShowMeMsg cannot be accessed as a member of cmd41.this.cmd37.ShowMeMsg from class ShowMeMsg_2 in class Helper
        if(other.msg == this.msg){
                 ^Compilation Failed
Compilation Failed

Summary

This was a brief introduction to Scala classes. To a large extent classes in Scala are similar to classes in Java or C++.

Specifically, we touched on how to create simple classes in Scala, getters and setters and the private[this] qualifier. The getters and setters will be private if the field they correspond to is declared as such. The private[this] qualifier is even more restricitve; not even instances of the same class can access the field.

References

  1. Cay Horstmann, Scala for the Impatient 1st Edition