Classes: Mutator Methods (Setters)

Scala also lets you create “setter” methods in a class, and in Scala these are more commonly called mutators, because we don’t follow the Java set/get naming standard (i.e., setFirstName, setLastName, etc.). These are used to update the fields in a class.

To me, this is one of the quirkiest parts about the Scala language, so I’ve broken this out into a separate lesson.

A class with a “getter” (accessor) method

To look at setter methods, let’s start with a class that has only a getter (accessor) method:

class Employee(var firstName: String, var lastName: String):
    private var _salary = 0d                          // a private field
    def salary: Double = _salary                      // a getter method
    def fullName: String = s"$firstName $lastName"    // another getter
end Employee

In this example, _salary is a new private mutable field, and because its value is 0d, the field is implicitly defined as a Double with that initial value.

I also defined a public “getter” method named salary that returns the employee’s salary. In other languages like Java it’s recommended that a getter method be named getSalary, but Scala doesn’t have that standard. Scala believes more in the Uniform Access Principle, where in the future, salary can be the name of a method or a field. The main idea is that to the end user of your class, that detail shouldn’t matter to them.

Here’s how this class can be used:

val e = Employee("John", "Doe")

// print the constructor parameter fields
println(s"firstName = ${e.firstName}, lastName = ${e.lastName}")

// print the salary field
println(s"Salary = ${e.salary}")

When you run that code it prints this output:

firstName = John, lastName = Doe
Salary = 0.0

Adding a setter (mutator) method

So far you can access the employee’s salary, but you can’t modify it, so let’s fix that problem by adding a setter/mutator method:

class Employee(var firstName: String, var lastName: String):
    private var _salary = 0d
    def salary: Double = _salary

    // this is the new setter method:
    def salary_=(newSalary: Double): Unit =
        _salary = newSalary

    def fullName: String = s"$firstName $lastName"
end Employee

With this code the employee’s salary can now be changed as well as accessed:

val e = Employee("John", "Doe")

// update the salary field
e.salary = 1_000_000d

println(s"firstName = ${e.firstName}, lastName = ${e.lastName}")
println(s"Salary = ${e.salary}")

When run, that code results in this output:

firstName = John, lastName = Doe
Salary = 1000000.0

The Scala setter/mutator syntax

The setter syntax is a little unusual, so let’s look at it again:

def salary_=(newSalary: Double): Unit =
    _salary = newSalary

To me, the quirky thing about this is that the method has the name salary_=. While it’s a bit unusual, it’s a way of saying, “I want to override the = method for the salary field, to allow me to write code like this”:

e.salary = 1_000_000d

As I look at that salary_= syntax today, it’s probably one of the most unusual things about Scala, so if you get comfortable with that, everything else should be much more straightforward.

The complete Scala class

Here’s a documented version of this class that explains things a little more:

/**
 * Employee is a class that takes two constructor parameters,
 * and both parameters are mutable.
 */
class Employee(var firstName: String, var lastName: String):

    // This is a private, mutable field that has the Double type.
    // Note that the field is named _salary, but it could be named
    // theSalary, or any other meaningful name. Also, because the
    // field is private, it can’t be accessed outside the class.
    private var _salary = 0d

    // This is a “getter” method for the _salary field. Users
    // will call this method to get the current salary value.
    def salary: Double = _salary

    // This is the “setter” method for the _salary field. Users
    // will call this method to update the salary. Note that it
    // can be declared on one line, but I use two lines here to
    // make it more clear.
    def salary_=(newSalary: Double): Unit =
        _salary = newSalary

    // This method returns the full name of the Employee as a
    // String.
    def fullName: String = s"$firstName $lastName"
end Employee

Now you can use that class as it’s shown in all the previous examples.

Note: This example comes from my book, Learn Scala 3 The Fast Way!