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.
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |