Kotlin Inheritance – Parent Class, Child Class, open, and override
Kotlin Inheritance is an object-oriented programming concept where one class can reuse and extend the behavior of another class. The class being inherited is called the parent class, base class, or superclass. The class that inherits it is called the child class, derived class, or subclass.
In Kotlin, classes are final by default. This means a class cannot be inherited unless it is marked with the open keyword. Similarly, a function or property cannot be overridden in a child class unless it is also marked open in the parent class.
- One class can inherit another class using the colon
:syntax. - The class being inherited is called Parent, Base, or Super class.
- The class that inherits another class is called Child, Derived, or Sub class.
- Child classes can use accessible properties and methods of the parent class.
- A parent class can have many child classes, but a Kotlin child class can inherit only one class directly.
- Kotlin supports multiple behavior contracts through interfaces, but not multiple class inheritance.
Where to identify and use inheritance in Kotlin programming?
Inheritance could be used where a group of classes would have some of the behaviours in common. For example : Student and Teacher are two different class of persons, but they belong to Person category. Here Student and Teacher could have their own specific behaviours like activity(), profession(), but they have some behaviours like eating, sleeping, etc. in common.
While designing an application containing Student, Teacher, etc., if we create a Parent class called Person, we could have the common behaviours of Student, Teacher, etc., in Person and any specific behaviours in their own class definition.
Use inheritance when there is a clear is-a relationship. For example, a Student is a Person, and a Teacher is also a Person. If the relationship is only about using another object as a part, composition is usually better. For example, a Car has an Engine; it should not normally inherit from Engine.
Syntax – Kotlin Inheritance
Following is the syntax to declare a class to inherit another class in Kotlin.
open class ParentClass(primary_constructor){
// common behaviour
}class ChildClass(primary_constructor): ParentClass(primary_constructor_initialization){
// ChildClass specific behaviours
}
The important points in this syntax are the open keyword and the constructor call after the parent class name. If the parent class has a primary constructor, the child class must initialize it while inheriting.
open class ParentClass(val value: String)
class ChildClass(value: String) : ParentClass(value)
Why Kotlin requires open for inheritance
Unlike some other object-oriented languages, Kotlin does not make classes inheritable by default. A class is final unless it is declared as open, abstract, or another inheritable form. This makes inheritance an explicit design decision.
open class Person
class Student : Person()
If Person is not marked open, the child class declaration fails because Kotlin does not allow extending a final class.
class Person
// Error: this type is final, so it cannot be inherited from
class Student : Person()
Example 1 – Kotlin Inheritance
In this example, we demonstrate Inheritance in Kotlin. We define a super class named Person. Also we define child classes: Teacher and Student that extend Person class.
Kotlin Program – example.kt
fun main(args: Array<String>) {
var student_1 = Student("Arjun")
var teacher_1 = Teacher("Amit")
println("\n\nAbout "+student_1.name+"\n---------------")
student_1.doAll()
println("\n\nAbout "+teacher_1.name+"\n---------------")
teacher_1.doAll()
}
/**
* Person is a Parent Class
*/
open class Person(var role: String = "Person", var name: String = "X") {
fun eat(){
println(name + " is eating.")
}
fun sleep(){
println(name + " is sleeping.")
}
}
/**
* Student class inherits Person class
*/
class Student(name: String): Person("Student", name) {
// activity function belongs to Student only
fun activity(){
println("$name is a $role. $name is studying in school.")
}
fun doAll(){
eat()
sleep()
activity()
}
}
/**
* Student class inherits Person class
*/
class Teacher(name: String): Person("Teacher", name) {
fun profession(){
println("$name is a $role. $name teaches at school.")
}
fun doAll(){
eat()
sleep()
profession()
}
}
When the above program is run, you will get the following output.
Output
About Arjun
---------------
Arjun is eating.
Arjun is sleeping.
Arjun is a Student. Arjun is studying in school.
About Amit
---------------
Amit is eating.
Amit is sleeping.
Amit is a Teacher. Amit teaches at school.
Takeaways from the above Example
- Variables : name, role belong to Person Class. But they are accessible to Student and Teacher classes because of inheritance.
- Methods : eat(), sleep() belong to Person Class. But they are accessible to Child classes because of inheritance.
- Observe the primary constructors of Parent class and Child class. Child class does not have var keyword for variable : name in the definition, hence it refers to the variable of Parent class. This is kind of variable overloading. Behaviours could also be overwritten. We shall learn about method overloading in next tutorial.
- The inheritance definition in Child class should at-least provide primary constructor of Parent Class.
class Student constructor(name: String): Person("Student", name)Student, while inheriting Person, provided values for primary constructor (role, name).
- The code maintenance for the methods : eat() and sleep() becomes simple, because there is only one place in the code where you need to change if there is a requirement to alter the behaviour.
Overriding open functions in Kotlin child classes
A child class can provide its own implementation of a parent class function only when the parent function is declared with open. The child class must use the override keyword. This makes overridden behavior clear in the code.
fun main() {
val person = PersonDetails("Person")
val student = StudentDetails("Arjun")
person.introduce()
student.introduce()
}
open class PersonDetails(val name: String) {
open fun introduce() {
println("I am $name.")
}
}
class StudentDetails(name: String) : PersonDetails(name) {
override fun introduce() {
println("I am $name. I am a student.")
}
}
I am Person.
I am Arjun. I am a student.
If the child class still needs the parent implementation, call it using super. This is useful when the child behavior should add to the parent behavior instead of replacing it completely.
override fun introduce() {
super.introduce()
println("I am also a student.")
}
Overriding Kotlin properties in a subclass
Kotlin also allows properties to be overridden. As with functions, the parent property must be marked open, and the child property must use override.
fun main() {
val employee = Employee("Meera")
println(employee.role)
}
open class User(val name: String) {
open val role: String = "User"
}
class Employee(name: String) : User(name) {
override val role: String = "Employee"
}
Employee
Calling a Kotlin parent class constructor from a child class
When a parent class has a primary constructor, the child class must call that constructor after the parent class name. This is why Student(name: String): Person("Student", name) passes values to the Person constructor in the earlier example.
open class Account(val accountNumber: String)
class SavingsAccount(accountNumber: String, val interestRate: Double) : Account(accountNumber)
Here, SavingsAccount has its own property interestRate, and it also initializes the parent class property accountNumber through the Account constructor.
Kotlin abstract class inheritance for incomplete parent behavior
Use an abstract class when the parent class should provide some common behavior but should not be created directly as an object. Abstract members do not need open; they must be implemented by a non-abstract child class.
fun main() {
val cardPayment = CardPayment(500.0)
cardPayment.pay()
}
abstract class Payment(val amount: Double) {
fun printAmount() {
println("Amount: $amount")
}
abstract fun pay()
}
class CardPayment(amount: Double) : Payment(amount) {
override fun pay() {
printAmount()
println("Paid by card")
}
}
Amount: 500.0
Paid by card
Single class inheritance and multiple interfaces in Kotlin
A Kotlin class can inherit from only one class directly. However, it can implement multiple interfaces. Use a class when you need shared state or common implementation. Use interfaces when you want to define capabilities that different classes can implement.
open class PersonBase(val name: String)
interface Learner {
fun learn()
}
interface Player {
fun play()
}
class SchoolStudent(name: String) : PersonBase(name), Learner, Player {
override fun learn() {
println("$name is learning.")
}
override fun play() {
println("$name is playing.")
}
}
Kotlin inheritance common mistakes
- Forgetting
openon the parent class: A normal Kotlin class is final and cannot be inherited. - Forgetting
openon parent functions: A child class cannot override a final function. - Missing
overridein the child class: Kotlin requiresoverridefor overridden functions and properties. - Not calling the parent constructor: If the parent class has a primary constructor, the child class must initialize it.
- Using inheritance for every reuse case: Use inheritance only for clear is-a relationships. Prefer composition for has-a relationships.
- Expecting multiple class inheritance: Kotlin allows one direct parent class, but a class can implement multiple interfaces.
Kotlin inheritance FAQs
Why do we use open class in Kotlin inheritance?
We use open because Kotlin classes are final by default. A class must be marked open before another class can inherit from it.
Can a Kotlin class inherit more than one class?
No. A Kotlin class can directly inherit only one class. It can, however, implement multiple interfaces.
How do you override a method in Kotlin inheritance?
Declare the parent method with open and implement it in the child class using override. Without open, the parent method cannot be overridden.
When should I use an abstract class instead of an open class in Kotlin?
Use an abstract class when the parent class represents a common base that should not be instantiated directly and when some members must be implemented by child classes.
What is the difference between Kotlin inheritance and composition?
Inheritance models an is-a relationship, such as Student is a Person. Composition models a has-a relationship, such as Car has an Engine. Composition is often safer when you only need to reuse behavior through another object.
Editorial QA checklist for this Kotlin inheritance tutorial
- Does the tutorial clearly state that Kotlin classes and methods are final by default?
- Does every inheritance example use
open,override, and constructor calls correctly? - Does the article distinguish parent class, child class, superclass, and subclass terms without mixing them?
- Does the tutorial explain single class inheritance and multiple interface implementation in Kotlin?
- Does the article warn against using inheritance where composition is more suitable?
- Do the examples show both inherited behavior and child-specific behavior?
Conclusion – Kotlin inheritance with open parent classes
In this Kotlin Tutorial – Kotlin Inheritance, we have learnt what Inheritance mean in Object Oriented Programming, how to implement inheritance in Kotlin programming with an example Kotlin program. We also covered the Kotlin-specific rules for open classes, override functions, parent constructors, abstract classes, and interfaces.
TutorialKart.com