Scala - Stateful Objects



This chapter takes you through the concept of stateful objects in Scala programming. Stateful objects are instances of classes. Stateful objects maintain state through fields and can change this state over time through methods.

Stateful Objects

Stateful objects are objects that maintain internal state across method calls. This state can be changed over time. So, this object reflects different conditions and behaviors based on its state.

Stateful object is an instance of class that contains fields (variables) representing its state and methods that can modify this state.

Syntax

The syntax of this stateful objects is -

class ClassName {
  var state: Type = initialValue

  def method(parameters: Type): ReturnType = {
    // Modify state
  }
}

Example

The following example shows simple stateful object in Scala programming -

class Counter {
  private var count = 0

  def increment(): Unit = {
    count += 1
  }

  def decrement(): Unit = {
    count -= 1
  }

  def currentCount(): Int = count
}

object Demo {
  def main(args: Array[String]): Unit = {
    val counter = new Counter
    counter.increment()
    println(s"Current count: ${counter.currentCount()}")
    counter.increment()
    println(s"Current count: ${counter.currentCount()}")
    counter.decrement()
    println(s"Current count: ${counter.currentCount()}")
  }
}

Save the above program in Demo.scala. The following commands are used to compile and execute this program.

Command

\>scalac Demo.scala
\>scala Demo

Output

Current count: 1
Current count: 2
Current count: 1

In the example, Counter class is a stateful object with a private field count representing its state. There are methods: increment, decrement, and currentCount. These methods modify and access the state. Demo object creates the instance of Counter class and interacts with it to change and retrieve its state.

Stateful Objects with Multiple Fields

Stateful objects can have multiple fields. These fields represent different aspects of their state. Each field can be independently modified and accessed through methods.

Syntax

The syntax of stateful objects with multiple fields is -

class ClassName {
  var field1: Type1 = initialValue1
  var field2: Type2 = initialValue2

  def method1(parameters: Type): ReturnType = {
    // Modify field1
  }

  def method2(parameters: Type): ReturnType = {
    // Modify field2
  }
}

Example

The following example shows stateful object with multiple fields -

class BankAccount(private var balance: Double, private var accountNumber: String) {

  def deposit(amount: Double): Unit = {
    if (amount > 0) balance += amount
  }

  def withdraw(amount: Double): Unit = {
    if (amount > 0 && amount <= balance) balance -= amount
  }

  def getBalance: Double = balance

  def getAccountNumber: String = accountNumber
}

object Demo {
  def main(args: Array[String]): Unit = {
    val account = new BankAccount(1000.0, "12444")
    println(s"Account Number: ${account.getAccountNumber}, Balance: ${account.getBalance}")
    account.deposit(500.0)
    println(s"Account Number: ${account.getAccountNumber}, Balance: ${account.getBalance}")
    account.withdraw(200.0)
    println(s"Account Number: ${account.getAccountNumber}, Balance: ${account.getBalance}")
  }
}

Save the above program in Demo.scala. The following commands are used to compile and execute this program.

Command

\>scalac Demo.scala
\>scala Demo

Output

Account Number: 12444, Balance: 1000.0
Account Number: 12444, Balance: 1500.0
Account Number: 12444, Balance: 1300.0

In the example, BankAccount class is a stateful object with two fields: balance and accountNumber. There are methods: deposit, withdraw, getBalance, and getAccountNumber. These methods modify and access these fields. Demo object creates the instance of BankAccount class and interacts with it to change and retrieve its state.

Immutable State

While stateful objects involve mutable state. It is possible to use immutable state where the object state cannot be changed after it is initialized. Immutable state provides safer and more predictable code.

Syntax

class ClassName(val state: Type)

Example

The following example shows an object with immutable state in Scala.

class Point(val x: Int, val y: Int) {
  def move(dx: Int, dy: Int): Point = {
    new Point(x + dx, y + dy)
  }

  override def toString: String = s"Point(x: $x, y: $y)"
}

object Demo {
  def main(args: Array[String]): Unit = {
    val point1 = new Point(10, 20)
    println(point1)
    val point2 = point1.move(5, 5)
    println(point2)
  }
}

Save the above program in Demo.scala. The following commands are used to compile and execute this program.

Command

\>scalac Demo.scala
\>scala Demo

Output

Point(x: 10, y: 20)
Point(x: 15, y: 25)

In the example, Point class represents object with immutable state. The move method returns new Point instance with modified coordinates. Rather than changing the state of the existing instance. Demo object creates instances of the Point class. It uses the move method to create new instances with different state.

Managing State Transitions

You can manage state transitions with defining clear and controlled ways for object state to change. So, this object remains in a valid state throughout its lifecycle.

Syntax

The syntax for managing state transitions is -

class ClassName {
  private var state: Type = initialValue

  def transition(newState: Type): Unit = {
    // Validate and apply state transition
  }

  def getState: Type = state
}

Example

The following example shows managing state transitions in a stateful object -

class TrafficLight(private var color: String) {
  private val validColors = Set("Red", "Yellow", "Green")

  def changeColor(newColor: String): Unit = {
    if (validColors.contains(newColor)) {
      color = newColor
    } else {
      println(s"Invalid color: $newColor")
    }
  }

  def currentColor(): String = color
}

object Demo {
  def main(args: Array[String]): Unit = {
    val trafficLight = new TrafficLight("Red")
    println(s"Current color: ${trafficLight.currentColor()}")
    trafficLight.changeColor("Green")
    println(s"Current color: ${trafficLight.currentColor()}")
    trafficLight.changeColor("Blue")
    println(s"Current color: ${trafficLight.currentColor()}")
  }
}

Save the above program in Demo.scala. The following commands are used to compile and execute this program.

Command

\>scalac Demo.scala
\>scala Demo

Output

Current color: Red
Current color: Green
Invalid color: Blue
Current color: Green

In the example, TrafficLight class is a stateful object with a field color representing its state. The changeColor method manages state transitions with validating the new color before applying it. Demo object creates instance of TrafficLight class. And interacts with it to change its state. So that only valid state transitions occur.

Scala Stateful Objects Summary

  • Stateful objects in Scala maintain internal state through fields. It can change this state over time through methods.
  • Stateful objects can have multiple fields. It represents different aspects of their state.
  • Immutable state has objects whose state cannot be changed after initialization. So provides safer and more predictable code.
  • Managing state transitions with defining controlled ways for object state to change. So the object remains in a valid state.
Advertisements