Kotlin is a modern programming language that provides expressive syntax and concise code. One essential aspect of Kotlin is its approach to constructors. While Kotlin allows both primary and secondary constructors, developers often encounter the error message "Primary constructor call expected" when dealing with inheritance in Kotlin. In this article, we will explore Kotlin's constructor mechanisms and how to properly instantiate classes to avoid this common pitfall.
Understanding Kotlin Constructors
In Kotlin, a primary constructor is part of the class header. It enables concise and direct initialization of properties. Let's look at a simple example:
class Animal(val name: String, val age: Int) {
// The primary constructor directly initializes properties.
}
val dog = Animal("Buddy", 3)The Animal class has a primary constructor that takes two parameters: name and age. This compact form is one of Kotlin's powerful features. However, what happens when inheritance is introduced?
The Issue: "Primary Constructor Call Expected"
When a class is extended in Kotlin, the primary constructor of the base class must be called. If not, you will encounter the error "Primary constructor call expected". Here's what a base class with a primary constructor looks like:
open class Animal(val name: String, val age: Int)An attempt to extend Animal without calling its primary constructor results in an error:
class Dog : Animal {
// Error: Primary constructor call expected.
}Fixing the Error
To resolve this, you must invoke the primary constructor of the base class. You can accomplish this by passing the necessary arguments in the derived class’s constructor:
class Dog(name: String, age: Int, val breed: String) : Animal(name, age) {
// The Animal's primary constructor is called with 'name' and 'age'.
}
val goldenRetriever = Dog("Buddy", 3, "Golden Retriever")By calling Animal(name, age) in the derived class Dog, you comply with Kotlin's inheritance requirements and avoid the "Primary constructor call expected" error.
Working with Secondary Constructors
Kotlin also supports secondary constructors, which provide additional means to initialize a class. Even when a class has a secondary constructor, it must still respect the primary constructor of its base class.
open class Animal(val name: String) {
var age: Int = 0
constructor(name: String, age: Int) : this(name) {
this.age = age
}
}
class Cat : Animal {
constructor(name: String, age: Int) : super(name, age) {
// Secondary constructor of Cat must call the primary or another constructor of Animal.
}
}
val kitten = Cat("Whiskers", 1)In this case, the Cat class has a secondary constructor which calls a secondary constructor in Animal that, in turn, calls its primary constructor.
Conclusion
Understanding the requirements for calling constructors in Kotlin is crucial when working with class inheritance. Ensuring that base class primary constructors are properly initialized prevents errors and promotes a better design in your Kotlin applications.
By following these guidelines, you can efficiently utilize Kotlin’s constructor paradigms to create robust and flexible object-oriented structures without encountering the "Primary constructor call expected" error.