Kotlin Inheritance Explained: Write Smarter, Reusable Code
Kotlin makes object-oriented programming simple and powerful with its inheritance system. If you’re coming from Java or another OOP language, understanding Kotlin inheritance will help you write smarter, reusable code with fewer lines and more efficiency.
In this guide, we’ll break down Kotlin inheritance step by step, making it easy to grasp and apply in real-world scenarios.
What Is Kotlin Inheritance?
Inheritance is a fundamental concept in object-oriented programming (OOP). It allows a class to acquire the properties and behaviors of another class, reducing code duplication and improving maintainability.
In Kotlin, inheritance works by creating a base class (parent class) and allowing other classes (child classes) to derive from it.
By default, all Kotlin classes are final (cannot be inherited). To make a class inheritable, you must explicitly use the open keyword.
// Parent class
open class Animal {
fun eat() {
println("This animal is eating")
}
}
// Child class inheriting from Animal
class Dog : Animal() {
fun bark() {
println("The dog is barking")
}
}
fun main() {
val myDog = Dog()
myDog.eat() // Inherited method
myDog.bark() // Child class method
}Here,
- The
Animalclass is open, making it inheritable. - The
Dogclass extendsAnimalusing the:symbol. - The
Dogclass gets access to theeat()function fromAnimal. - The
bark()function is specific toDog.
Primary Constructor in Kotlin Inheritance
When a child class inherits from a parent class that has a constructor, it must initialize it. Here’s how it works:
open class Animal(val name: String) {
fun eat() {
println("$name is eating")
}
}
class Dog(name: String) : Animal(name) {
fun bark() {
println("$name is barking")
}
}
fun main() {
val myDog = Dog("Buddy")
myDog.eat()
myDog.bark()
}What’s Happening Here?
- The
Animalclass has a primary constructor with anameparameter. - The
Dogclass calls theAnimalconstructor using: Animal(name). - When we create a
Dogobject, we pass a name that is used in botheat()andbark().
Overriding Methods in Kotlin
Kotlin allows child classes to modify or override methods from the parent class using the override keyword.
open class Animal {
open fun makeSound() {
println("Animal makes a sound")
}
}
class Dog : Animal() {
override fun makeSound() {
println("Dog barks")
}
}
fun main() {
val myDog = Dog()
myDog.makeSound()
}Here,
- The
makeSound()function inAnimalis open, allowing it to be overridden. Dogprovides its own implementation usingoverride.- Now, when
makeSound()is called onDog, it prints “Dog barks” instead of “Animal makes a sound”.
If we remove open from the method but keep the class open, will it affect our code? Yes, we will get the following compile-time error:
'makeSound' in 'Animal' is final and cannot be overridden.Using Superclass Methods
Sometimes, you want to modify a method but still call the original method from the parent class. You can do this using super.
open class Animal {
open fun makeSound() {
println("Animal makes a sound")
}
}
class Dog : Animal() {
override fun makeSound() {
super.makeSound()
println("Dog barks")
}
}
fun main() {
val myDog = Dog()
myDog.makeSound()
}Here, super.makeSound() calls the parent class method before executing the child class implementation.
Abstract Classes in Kotlin Inheritance
An abstract class cannot be instantiated and may contain abstract methods that must be implemented by child classes.
abstract class Animal {
abstract fun makeSound()
}
class Dog : Animal() {
override fun makeSound() {
println("Dog barks")
}
}
fun main() {
val myDog = Dog()
myDog.makeSound()
}Why Use Abstract Classes?
- They define a template for subclasses.
- They ensure that all child classes implement necessary methods.
Interfaces vs. Inheritance in Kotlin
Kotlin also supports interfaces, which are similar to abstract classes but allow multiple implementations.
interface Animal {
fun makeSound()
}
class Dog : Animal {
override fun makeSound() {
println("Dog barks")
}
}
fun main() {
val myDog = Dog()
myDog.makeSound()
}Key Differences:
- A class can inherit only one superclass but implement multiple interfaces.
- Interfaces cannot store state (i.e., no instance variables), while abstract classes can.
Conclusion
Kotlin inheritance is a powerful feature that helps you write smarter, reusable code. By using open classes, overriding methods, abstract classes, and interfaces, you can structure your code efficiently.
Here’s a quick recap:
- Use
opento make a class inheritable. - Override methods with
override. - Use
superto call the parent method. - Use
abstractfor mandatory implementations.
By mastering Kotlin inheritance, you can build scalable, maintainable, and clean applications.










