In Scala, the object
keyword creates a Singleton object.
Put another way, an object defines a class that has exactly one instance.
Objects have several uses:
- They are used to create collections of utility methods.
- A companion object is an object that has the same name as the class it shares a file with. In this situation, that class is also called a companion class.
- They’re used to implement traits to create modules.
“Utility” methods
Because an object
is a Singleton, its methods can be accessed like static
methods in a Java class.
For example, this StringUtils
object contains a small collection of string-related methods:
object StringUtils {
def isNullOrEmpty(s: String): Boolean = s == null || s.trim.isEmpty
def leftTrim(s: String): String = s.replaceAll("^\\s+", "")
def rightTrim(s: String): String = s.replaceAll("\\s+$", "")
}
object StringUtils:
def isNullOrEmpty(s: String): Boolean = s == null || s.trim.isEmpty
def leftTrim(s: String): String = s.replaceAll("^\\s+", "")
def rightTrim(s: String): String = s.replaceAll("\\s+$", "")
Because StringUtils
is a singleton, its methods can be called directly on the object:
val x = StringUtils.isNullOrEmpty("") // true
val x = StringUtils.isNullOrEmpty("a") // false
Companion objects
A companion class or object can access the private members of its companion. Use a companion object for methods and values which aren’t specific to instances of the companion class.
This example demonstrates how the area
method in the companion class can access the private calculateArea
method in its companion object:
import scala.math._
class Circle(radius: Double) {
import Circle._
def area: Double = calculateArea(radius)
}
object Circle {
private def calculateArea(radius: Double): Double =
Pi * pow(radius, 2.0)
}
val circle1 = new Circle(5.0)
circle1.area // Double = 78.53981633974483
import scala.math.*
class Circle(radius: Double):
import Circle.*
def area: Double = calculateArea(radius)
object Circle:
private def calculateArea(radius: Double): Double =
Pi * pow(radius, 2.0)
val circle1 = Circle(5.0)
circle1.area // Double = 78.53981633974483
Creating modules from traits
Objects can also be used to implement traits to create modules.
This technique takes two traits and combines them to create a concrete object
:
trait AddService {
def add(a: Int, b: Int) = a + b
}
trait MultiplyService {
def multiply(a: Int, b: Int) = a * b
}
// implement those traits as a concrete object
object MathService extends AddService with MultiplyService
// use the object
import MathService._
println(add(1,1)) // 2
println(multiply(2,2)) // 4
trait AddService:
def add(a: Int, b: Int) = a + b
trait MultiplyService:
def multiply(a: Int, b: Int) = a * b
// implement those traits as a concrete object
object MathService extends AddService, MultiplyService
// use the object
import MathService.*
println(add(1,1)) // 2
println(multiply(2,2)) // 4