In this article you will learn about the constructors and what happens when the object is created or instantiated.
Constructors
A constructor is used to initialize the properties of a class. When an object is instantiated constructors get invoked automatically. There are two types of constructors in Kotlin – primary constructor and secondary constructor. Let’s go through the examples of both of these constructors.
Primary Constructor
This type of constructor is included in the class header itself as shown in the figure below. It can only have a list of parameters and no code.
class Car constructor(carModel: String, color: String) { /* *** */ }
The constructor keyword is optional when we are not using any annotation or visibility modifier in the primary constructor.
class Car (carModel: String, color: String) { /* *** */ }
Let’s see an example of a constructor and how the constructor parameters can be used in the code.
class Car constructor(carModel: String, color: String) {
val carType = "Car Mode = $carModel"
init {
println("Your $carType and color = $color")
}
}
fun main(args: Array<String>) {
val bmw = Car("bmw_xyz", "Red")
} // Output: Your Car Mode = bmw_xyz and color = Red
The blocks of code from line 3 to 4 in the above example which starts with the keyword init is known as an initializer block. When the object is created, the constructor is invoked where its parameters are initialized (line 1) and the initialization statement is executed (line 2) and finally, the initializer block is called.
Note that, the parameters of the constructor can only be used in an initializer block and the initialization statement. Any attempt to use it anywhere else lead to the compile-time error.
class Car constructor(carModel: String, color: String) {
val carType = "Car Mode = $carModel"
init {
println("Your $carType and color = $color")
}
fun drive(distance: Int) {
println("You just drove $distance kilometers in your $carModel car")
}
}
fun main(args: Array<String>) {
val bmw = Car("bmw_xyz", "Red")
}
If you want to be able to use it somewhere else like inside a function then you should mark the constructor parameters as val or var based on your needs of mutability. Let’s make the above code work.
class Car(val carModel: String, val color: String) {
val carType = "Car Mode = $carModel"
init {
println("Your $carType and color = $color")
}
fun drive(distance: Int) {
println("You just drove $distance kilometers in your $carModel car")
}
}
fun main(args: Array<String>) {
val bmw = Car("bmw_xyz", "Red")
}
Default values in the constructor
We can also pass default values to the constructor.
class Car(val carModel: String = "xyz", val color: String) {
fun drive(distance: Int) {
println("You just drove $distance kilometers in your $carModel car")
}
}
fun main(args: Array<String>) {
val bmw = Car("bmw_xyz", "Red")
bmw.drive(250)
val mercedes = Car("mercedes123")
mercedes.drive(300)
val toyota = Car(color = "blue", carModel = "toyota")
toyota.drive(60)
}
In the above example, you can see that we have provided default value to the properties of the constructor. In Line 11, we have used the default value to the color property. In line 14, we have altered the order of properties and it was possible because we have used the name of an argument to assign value to properties. This feature is known as the Named Argument in Kotlin.
Default constructor
It is perfectly ok to not have any constructor defined in our class at all. In that case, the compiler will implicitly add the default empty primary constructor for us. Let’s see an example.
class Car {
val carModel: String = "xyz"
val color: String = "transparent"
fun drive(distance: Int) {
println("You just drove $distance kilometers in your $carModel car")
}
}
fun main(args: Array<String>) {
val bmw = Car()
bmw.drive(250)
}
Even though the class Car does not have any constructor, we can still instantiate the object using val bmw = Car() that’s because the compiler provides the default empty constructor on our behalf.
Secondary Constructor
In the secondary constructor, on top of the properties of the class, we can have additional code inside of it. Also, the constructor keyword is mandatory unlike in the primary constructor.
class Car {
var model: String = ""
var color: String = ""
var name: String = ""
constructor(carModel: String = "xyz", color: String = "Red") {
model= carModel
this.color = color
name = "$model $color"
}
fun drive(distance: Int) {
println("You just drove $distance kilometers in your $carModel car")
}
}
fun main(args: Array<String>) {
val bmw = Car("bmw_xyz", "Red")
bmw.drive(250)
}
Let’s see an example where we have both the primary and secondary constructors.
class Car(val carModel: String, val color: String) {
var carName = ""
constructor(name: String) : this(name, "") {
carName = name
println("Car Name is: $name")
}
}
When we have both constructors, then each secondary constructor needs to delegate to the primary constructor, either directly or indirectly through another secondary constructor(s) using this keyword as shown in line 4.
We can have multiple secondary constructors but only one primary constructor. Let’s see another example to understand the direct and indirect delegation via a secondary constructor.
class Car(val carNumber: Int) {
init {
println("Execute initializer block")
}
constructor(name: String) : this(0) {
println("Car Name is: $name")
}
constructor(name: String, color: String) : this(name) {
println("Car Name is: $name color: $color")
}
}
fun main(args: Array<String>) {
val bmw = Car("bmw123", "Yellow")
}
//Output:
/*
* Execute initializer block
* Car name is: bmw123
* Car name is: bmw123 color: Yellow
The number in the code represents the order of an execution when the object is instantiated. Click on the next button to continue reading.
No responses yet