Kotlin inheritance explanation with example

Introduction to inheritance :

Inheritance is a commonly used concept in object-oriented programming. It is the way to inherit functions and properties from a base class to a child class.

If we have common properties in different classes, we can put them in a single class and make this class parent class of all other classes. This parent class is also called a base class or superclass and the other classes are called child class or derived class.

By default, all classes in Kotlin are child classes of class Any and they inherit three methods: equals(), hashCode() and toString().

Kotlin doesn’t provide multiple inheritance i.e. we can’t inherit from more than one class.

In this tutorial, I will explain how to implement inheritance in Kotlin with examples.

Can we make all Kotlin class parent class :

By default, all classes are final in Kotlin. So, we can’t have any class that inherits from these classes. To make any class inheritable, we need to make them open. For example,

open class Car(id: Int)

Now, we can create one child class of Car :

class Audi(id: Int) : Car(id)
  • Audi is the derived class and Car is the base class.
  • A base class is set after a colon :
  • If the derived class has a primary constructor, we need to initialize it using the parameters like above.
  • If the derived class doesn’t have any primary constructor, then the base class is initialized using super keyword with the secondary constructor of the derived class. For multiple secondary constructors in the base class, a derived class constructor can call any secondary constructor.
class Audi() : Car(){
    constructor(id: Int) : super(id)
}

This example is for secondary constructors.

Overriding methods of the base class :

Make one method open if you want it to override in the child class :

open class Car(val carId: String) {
    open fun printId() {
        print("Id for car is ${carId}")
    }
}

class Audi(val audiId: String) : Car(audiId) {
    override fun printId() {
        print("Id for Audi is ${audiId}")
    }
}

override methods are open by default. So, we can override them in subclasses. You can use final if you want to prohibit re-overriding of these methods.

Override properties :

It works similarly to method overriding. Properties should be open if you want to override them and we need to use override keyword for that.

val property can be overridden as var but not vice versa. Also, we can override in the constructor.

open class Car {
    open val color: String = "Red"
    open val type: String = "car"
    open val id: String = "id-car"
}

class Audi(override val type: String = "audi") : Car() {
    override var color = "Blue"
    override val id = "id-audi"
}

Here, type is overridden in the primary constructor, color is changed to var, and id is overridden without changing the property.

super keyword :

super is used to access parent class. For example :

open class Car {
    open fun printDetails(){
        println("Inside car")
    }
}

class Audi : Car() {
    override fun printDetails(){
        super.printDetails()
        println("Inside Audi")
    }
}

fun main() {
    val audi = Audi()
    audi.printDetails()
}

Here, it will invoke the printDetails method of Car class first before printing the message of Audi. It will print :

Inside car
Inside Audi

If we have multiple inheritance like one class and one interface with the similar method name, we need to specify the name of the class or interface with super inside an angular bracket :

open class Car {
    open fun printDetails() {
        println("Inside car")
    }
}
interface Base {
    fun printDetails() {
        println("Inside interface")
    }
}
class Audi : Car(), Base {
    override fun printDetails() {
        super<car>.printDetails()
        super<base>.printDetails()
        println("Inside Audi")
    }
}
fun main() {
    val audi = Audi()
    audi.printDetails()
}

It will print :

Inside car
Inside interface
Inside Audi

Similar tutorials :