How to call a Scala superclass constructor

This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 4.11, “How to call a Scala superclass constructor.”

Problem

You want to control a Scala superclass constructor that’s called when you create constructors in a subclass.

Solution

This is a bit of a trick question, because you can control the superclass constructor that’s called by the primary constructor in a subclass, but you can’t control the superclass constructor that’s called by an auxiliary constructor in the subclass.

When you define a subclass in Scala, you control the superclass constructor that’s called by its primary constructor when you define the extends portion of the subclass declaration. For instance, in the following code, the Dog class is defined to call the primary constructor of the Animal class, which is a one-arg constructor that takes name as its parameter:

class Animal (var name: String) {
    // ...
}

class Dog (name: String) extends Animal (name) {
    // ...
}

However, if the Animal class has multiple constructors, the primary constructor of the Dog class can call any of those constructors.

For example, the primary constructor of the Dog class in the following code calls the one-arg auxiliary constructor of the Animal class by specifying that constructor in its extends clause:

// (1) primary constructor
class Animal (var name: String, var age: Int) {

    // (2) auxiliary constructor
    def this (name: String) {
        this(name, 0)
    }
    override def toString = s"$name is $age years old"
}

// calls the Animal one-arg constructor
class Dog (name: String) extends Animal (name) {
    println("Dog constructor called")
}

Alternatively, it could call the two-arg primary constructor of the Animal class:

// call the two-arg constructor
class Dog (name: String) extends Animal (name, 0) {
    println("Dog constructor called")
}

Auxiliary constructors

Regarding auxiliary constructors, because the first line of an auxiliary constructor must be a call to another constructor of the current class, there is no way for auxiliary con‐ structors to call a superclass constructor.

As you can see in the following code, the primary constructor of the Employee class can call any constructor in the Person class, but the auxiliary constructors of the Employee class must call a previously defined constructor of its own class with the this method as its first line:

case class Address (city: String, state: String)
case class Role (role: String)

class Person (var name: String, var address: Address) {
    // no way for Employee auxiliary constructors to call this constructor
    def this (name: String) {
        this(name, null)
        address = null
    }
    override def toString = if (address == null) name else s"$name @ $address"
}

class Employee (name: String, role: Role, address: Address) extends Person (name, address) {
    def this (name: String) {
        this(name, null, null)
    }
    def this (name: String, role: Role) {
        this(name, role, null)
    }
    def this (name: String, address: Address) {
        this(name, null, address)
    }
}

Therefore, there’s no direct way to control which superclass constructor is called from an auxiliary constructor in a subclass. In fact, because each auxiliary constructor must call a previously defined constructor in the same class, all auxiliary constructors will eventually call the same superclass constructor that’s called from the subclass’s primary constructor.