How to provide default values for Scala constructor parameters

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 4.5, “How to provide default values for Scala constructor parameters.”

Problem

You want to provide a default value for a Scala constructor parameter, which gives other classes the option of specifying that parameter when calling the constructor, or not.

Solution

Give the parameter a default value in the constructor declaration. Here’s a simple declaration of a Socket class with one constructor parameter named timeout that has a default value of 10000:

class Socket (val timeout: Int = 10000)

Because the parameter is defined with a default value, you can call the constructor without specifying a timeout value, in which case you get the default value:

scala> val s = new Socket
s: Socket = Socket@7862af46

scala> s.timeout
res0: Int = 10000

You can also specify the desired timeout value when creating a new Socket:

scala> val s = new Socket(5000)
s: Socket = Socket@6df5205c

scala> s.timeout
res1: Int = 5000

If you prefer the approach of using named parameters when calling a constructor (or method), you can also use this approach to construct a new Socket:

scala> val s = new Socket(timeout=5000)
s: Socket = Socket@52aaf3d2

scala> s.timeout
res0: Int = 5000

Discussion

This recipe demonstrates a powerful feature that can eliminate the need for auxiliary constructors. As shown in the Solution, the following single constructor is the equivalent of two constructors:

class Socket (val timeout: Int = 10000)

If this feature didn’t exist, two constructors would be required to get the same functionality; a primary one-arg constructor and an auxiliary zero-args constructor:

class Socket(val timeout: Int) {
    def this() = this(10000)
    override def toString = s"timeout: $timeout"
}

Multiple parameters

Taking this approach a step further, you can provide default values for multiple constructor parameters:

class Socket(val timeout: Int = 1000, val linger: Int = 2000) {
    override def toString = s"timeout: $timeout, linger: $linger"
}

Though you’ve defined only one constructor, your class now appears to have three constructors:

scala> println(new Socket)
timeout: 1000, linger: 2000

scala> println(new Socket(3000))
timeout: 3000, linger: 2000

scala> println(new Socket(3000, 4000))
timeout: 3000, linger: 4000

Using named parameters

As shown in the Solution, you can also provide the names of constructor parameters when creating objects, in a manner similar to Objective-C and other languages. This means you can also create new Socket instances like this:

println(new Socket(timeout=3000, linger=4000))
println(new Socket(linger=4000, timeout=3000))
println(new Socket(timeout=3000))
println(new Socket(linger=4000))

See Recipe 5.4, “Using Parameter Names When Calling a Scala Method”, for more examples of how to use parameter names in method calls.

See Also