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+$", "")
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 = 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, MultiplyService
// use the object
import MathService.*
println(add(1,1)) // 2
println(multiply(2,2)) // 4
Contributors to this page:
Contents
- Introduction
- Scala 3 Features
- Why Scala 3?
- A Taste of Scala
- Hello, World!
- The REPL
- Variables and Data Types
- Control Structures
- Domain Modeling
- Methods
- First-Class Functions
- Singleton Objects
- Collections
- Contextual Abstractions
- Toplevel Definitions
- Summary
- A First Look at Types
- Control Structures
- Domain Modeling
- Tools
- OOP Modeling
- FP Modeling
- Methods
- Method Features
- main Methods
- Summary
- Functions
- Anonymous Functions
- Function Variables
- Eta Expansion
- Higher-Order Functions
- Write Your Own map Method
- Creating a Method That Returns a Function
- Summary
- Packaging and Imports
- Scala Collections
- Collections Types
- Collections Methods
- Summary
- Functional Programming
- What is Functional Programming?
- Immutable Values
- Pure Functions
- Functions Are Values
- Functional Error Handling
- Summary
- Types and the Type System
- Inferred Types
- Generics
- Intersection Types
- Union Types
- Algebraic Data Types
- Variance
- Opaque Types
- Structural Types
- Dependent Function Types
- Other Types
- Contextual Abstractions
- Given Instances and Using Clauses
- Type Classes
- Context Bounds
- Given Imports
- Extension Methods
- Implementing Type Classes
- Multiversal Equality
- Implicit Conversions
- Summary
- Concurrency
- Scala Tools
- Building and Testing Scala Projects with sbt
- Worksheets
- Interacting with Java
- Scala for Java Developers
- Scala for JavaScript Developers
- Scala for Python Developers
- Where To Go Next