How to provide default values for Scala constructor parameters

This is an excerpt from the Scala Cookbook (#ad) (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