Understanding of Constructors
In Scala, a class can have fields (variables) that store data associated with an object. Fields can be mutable (using var) or immutable (using val).
Whenever you try to create an object for a class, it internally calls a constructor. You use constructor to initialize the values to the fields of a class.

Constructor will execute whatever is present the class definition.

In the above example, the println statement in the class definition gets executed when constructor is called.
Default constructor
In Scala, a default constructor is automatically provided when you define a class, even if you don’t explicitly define a constructor. This default constructor is essentially the primary constructor, which is part of the class definition itself. The default constructor is invoked when you create an object of the class.
Let’s look at an example where the class does not have any explicit constructor parameters, but it has fields that get initialized with default values:
class Person {
// Fields inside the class body with default values
var name: String = "Unknown"
var age: Int = 0
// Method to display person details
def displayInfo(): Unit = {
println(s"Name: $name, Age: $age")
}
}
- Fields: The fields
nameandageare declared inside the class body with default values ("Unknown"fornameand0forage). - Methods: The
displayInfomethod prints the current values of the fields. - Default Constructor: Since there are no parameters passed to the class, the default constructor is automatically invoked, and the fields are initialized with their default values.
When you create an object without passing any parameters, Scala automatically uses the default constructor:
val person = new Person
person.displayInfo() // Output: Name: Unknown, Age: 0
In this example, since no parameters are provided, the default values of "Unknown" for the name and 0 for the age are used.
Types of Constructors in Scala
In Scala, the concept of constructors is a bit different from languages like Java. Scala does not have separate constructor methods for initialization; instead, it uses a combination of the primary constructor (implicitly defined) and auxiliary constructors (explicitly defined) to handle object creation and initialization.
Primary Constructor
The primary constructor is part of the class definition and is defined directly in the class header. It allows you to initialize class fields and perform setup tasks when an instance of the class is created.
Syntax :
class ClassName(param1: Type1, param2: Type2) {
// Class body
}
Ex:
class Person(val name: String, val age: Int) {
// Fields 'name' and 'age' are initialized via primary constructor
def displayInfo(): Unit = {
println(s"Name: $name, Age: $age")
}
}
val person = new Person("Alice", 30)
person.displayInfo() // Output: Name: Alice, Age: 30
Explanation:
class Person(val name: String, val age: Int):nameandageare constructor parameters.- The
valkeyword makes these parameters accessible as fields of the class.
- The primary constructor initializes the
nameandagefields and sets up the object.
Another example :
class Car(val brand: String, val model: String, var year: Int) {
// Method to print car details
def displayInfo(): Unit = {
println(s"Car: $brand $model, Year: $year")
}
// Method to update the year
def updateYear(newYear: Int): Unit = {
year = newYear
}
}
// Creating an object of Car class
val myCar = new Car("Toyota", "Corolla", 2020)
// Accessing fields and calling methods
myCar.displayInfo() // Output: Car: Toyota Corolla, Year: 2020
// Updating the year
myCar.updateYear(2022)
myCar.displayInfo() // Output: Car: Toyota Corolla, Year: 2022
The primary constructor is defined by passing parameters (brand, model, and year) when creating a new Car object. The val and var keywords allow these parameters to be used as fields in the class.
myCaris an instance of theCarclass, and it has thebrand,model, andyearfields initialized with"Toyota","Corolla", and2020respectively.
Auxiliary Constructors
Auxiliary constructors are additional constructors that provide alternative ways to initialize objects. They are defined using the def this(...) syntax and can call the primary constructor to ensure that the object is properly initialized.
Syntax :
class ClassName(param1: Type1) {
// Primary constructor
def this(param1: Type1, param2: Type2) = {
this(param1) // Call the primary constructor
// Additional initialization
}
}
Ex:
class Person(val name: String, val age: Int) {
// Auxiliary constructor
def this(name: String) = {
this(name, 0) // Call the primary constructor with a default age
}
def displayInfo(): Unit = {
println(s"Name: $name, Age: $age")
}
}
val person1 = new Person("Bob", 25)
val person2 = new Person("Carol") // Uses auxiliary constructor with default age
person1.displayInfo() // Output: Name: Bob, Age: 25
person2.displayInfo() // Output: Name: Carol, Age: 0
Explanation:
- Primary Constructor:
class Person(val name: String, val age: Int)initializes thenameandagefields. - Auxiliary Constructor:
def this(name: String)provides an alternative way to create aPersonwith a default age (0). It calls the primary constructor with a default value forage.
Key Points
- Primary Constructor:
- Defined in the class header.
- Used for initializing class fields and performing setup tasks.
- Parameters defined here become fields if declared with
valorvar.
- Auxiliary Constructors:
- Defined using
def this(...). - Can be used to provide additional ways to create objects.
- Must call the primary constructor to ensure proper initialization.
- Defined using
Conclusion :
Scala’s primary constructor provides a concise way to initialize class fields, while auxiliary constructors offer additional flexibility. By using these constructors appropriately, you can handle various object initialization scenarios effectively.
Primary Constructor with Default Parameters
You can also define a class with parameters in the primary constructor, but provide default values for these parameters. This allows you to create objects without passing arguments, in which case the default values will be used.
Here’s an example with default parameters in the primary constructor:
class Car(val brand: String = "Toyota", val model: String = "Corolla", var year: Int = 2020) {
// Method to display car details
def displayInfo(): Unit = {
println(s"Car: $brand $model, Year: $year")
}
}
Creating Objects with and without Parameters:
- Using Default Constructor (with default values):
val car1 = new Car()
car1.displayInfo() // Output: Car: Toyota Corolla, Year: 2020
- Providing Custom Values:
val car2 = new Car("Honda", "Civic", 2022)
car2.displayInfo() // Output: Car: Honda Civic, Year: 2022
Key Concepts
- Default Constructor: If no constructor parameters are defined, Scala provides a default constructor.
- Default Values: You can set default values for fields in the class body or for constructor parameters.
- Flexibility: You can define fields inside the class body or in the primary constructor, and Scala will handle initialization appropriately.
This approach allows you to create objects with or without passing arguments, depending on your needs.
Ex:
// Program no 3: Default parameters in constructor (Primary constructor)
class demoClass2(val a:Int = 99, val b:Double = 88.88, val c:String = "Hello Scala"){
val x = a
var y = b
val z = c
def addNumber() = {
x + y
}
println(s"x = ${x} and y = ${y} and z = ${z}")
}
object constructorDemo2 {
def main(args: Array[String]): Unit = {
val demoObject1 = new demoClass2(5,7.2,"Hello World!")
val demoObject2 = new demoClass2()
val demoObject3 = new demoClass2(25)
// val demoObject4 = new demoClass2("Hello") - You need to pass parameter in correct sequence, for out of sequence see next example
val demoObject5 = new demoClass2(c = "Hello") // positional parameters
val demoObject6 = new demoClass2(c = "Hello", a = 5, b = 6.6)
//val demoObject7 = new demoClass2( , , "hello") - can not do
//val demoObject8 = new demoClass2( a,b , "hello") - can not do, it does not know what is a and b simply, can be done as below
val demoObject9 = new demoClass2( a=5,b=5.5 , "hello")
}
}
Creating Classes with Parameters
We can call them as parameterized constructors.
- Define Parameters in Class: Include parameters in the class definition to define the primary constructor.
- Pass Arguments on Instantiation: Provide arguments for these parameters when creating an instance of the class.
- Use Auxiliary Constructors: Define additional constructors with
def this(...)for alternative ways to initialize the class with different sets of parameters.
This approach enables you to create flexible and customizable class instances in Scala.
Here’s a step-by-step guide to defining a class with parameters and creating instances of it:
1. Define a Class with Parameters
When defining a class, you specify the parameters directly in the class definition. These parameters are part of the primary constructor.
Example:
class Car(val make: String, val model: String, val year: Int) {
def displayInfo(): Unit = {
println(s"Make: $make, Model: $model, Year: $year")
}
}
val make: String: A parameter that is also a field of the class, accessible throughout the class.val model: String: Another parameter and field.val year: Int: A third parameter and field.
2. Create Instances of the Class with Parameters
When you create an instance of the class, you pass the arguments that correspond to the parameters defined in the primary constructor.
Example:
val myCar = new Car("Toyota", "Corolla", 2024)
myCar.displayInfo() // Output: Make: Toyota, Model: Corolla, Year: 2024
In this example:
"Toyota"is passed as themakeparameter."Corolla"is passed as themodelparameter.2024is passed as theyearparameter.
Ex:

3. Using Auxiliary Constructors
If you need to provide additional ways to create instances of a class with different sets of parameters, you can use auxiliary constructors.
Example with Auxiliary Constructor:
class Car(val make: String, val model: String, val year: Int) {
// Auxiliary constructor
def this(make: String, model: String) = {
this(make, model, 0) // Default year is 0
}
def displayInfo(): Unit = {
println(s"Make: $make, Model: $model, Year: $year")
}
}
val car1 = new Car("Honda", "Civic", 2022)
val car2 = new Car("Ford", "Focus") // Uses auxiliary constructor with default year
car1.displayInfo() // Output: Make: Honda, Model: Civic, Year: 2022
car2.displayInfo() // Output: Make: Ford, Model: Focus, Year: 0
- Primary Constructor: Initializes the
make,model, andyearfields. - Auxiliary Constructor: Allows creation of a
Carwith a default year if onlymakeandmodelare provided.
Ex: Auxiliary constructor
// Program no 4: Auxiliary constructors
class demoClass3(val a:Int, val b:Double, val c:String){
val x = a
var y = b
val z = c
println(s"Primary constructor says: x = ${x} and y = ${y} and z = ${z}")
def addNumber() = {
x + y
}
def this(){
this(99,88.88,"Hello Scala")
println("I came into Auxiliary constructor with 0 parameters")
}
def this(a:Int){
this(a,88.88,"Hello Scala")
println("I came into Auxiliary constructor with 1 parameters")
}
def this(a:Int, b:Double){
this(a,b,"Hello Scala")
println("I came into Auxiliary constructor with 2 parameters")
}
def this(c:String){
this(6,66.66,c)
println("I came into Auxiliary constructor with 1 paramter that was c:String")
}
}
object constructorDemo3 {
def main(args: Array[String]): Unit = {
val demoObject1 = new demoClass3(5,7.2,"Hello World!")
val demoObject2 = new demoClass3()
val demoObject3 = new demoClass3(7)
val demoObject4 = new demoClass3(7,2.2)
val demoObject5 = new demoClass3("Hello Java")
val demoObject6 = new demoClass3(a=5,b=7.2,c="Hello World!")
}
}
More details on val & var
// Program no 2: Parametrized Constructor (Primary constructor)
class demoClass1(val a:Int, val b:Double, val c:String){
val x = a //var(can change the value) and val (can not change the value):
var y = b // retrieve(GET) and change(SET) the content of y because it is a var >>> INTERNALLY SCALA CREATES 2 METHODS - GETTER AND SETTER
val z = c // ONLY retrieve(GET) the content of z because it is a val () >>> INTERNALLY SCALA CREATES ONLY 1 METHOD - GETTER
def addNumber() = {
x + y
}
println(s"x = ${x} and y = ${y} and z = ${z}")
}
object constructorDemo1 {
def main(args: Array[String]): Unit = {
val demoObject1 = new demoClass1(5,7.2,"Hello World!") //Object: Instance of class -> Calls Constructor
val demoObject2 = new demoClass1(6,8.3,"Hello World Again!") //Object: Instance of class -> Calls Constructor
// demoObject1.x =3 // Can not change(only retrieve) the content of x as it was defined as val in the class and hence it only has getter method
demoObject1.y = 7.22222 // can retrieve and change the content of y as it was defined as var inthe class and hence it has getter and setter method
println(demoObject1.x, demoObject1.y,demoObject1.z)
var result = demoObject1.addNumber()
println(s"result = ${result}")
println(demoObject2.x, demoObject2.y,demoObject2.z)
result = demoObject2.addNumber()
println(s"result = ${result}")
}
}