Kotlin Inheritance Tutorial

In this section, we will learn what inheritance is and how it works in Kotlin.

What is Inheritance in Kotlin?

Inheritance is the idea of letting one class to use the members of another class (properties and functions) instead of creating its own members, which can lead to copy and pasting the same source codes in two places!

For example, let’s say we have a class called Animal, and another one called Cat.

Now the Animal class has two functions called walk and eat. The Cat class also needs these two functions as part of its body.

So here, instead of creating the same functions in the Cat class, we can make this class to inherit from the Animal class and use the two functions that are already created there! This way we don’t duplicate our source code for the two functions, which helps to maintain the codes easier (because we only need to modify the functions in one place if ever needed).

Related Terminology to Inheritance in Kotlin

Before we get into the details on how to create inheritance in Kotlin, there are a set of terminologies that we should be familiar with because they will be used a lot by developers when it comes to inheritance.

Kotlin Super Class (Base Class | Parent Class):

A super class (AKA base class or Parent class) is the class that we want to let other classes to inherit and use its members.

Kotlin Subclass (Child Class):

Subclass or Child class is the one that is inheriting from other classes!

Kotlin Inheritance Declaration Syntax:

Alright, now let’s see how we can make one class to inherit from another class:

open class SuperClass{…}

The syntax above shows how to create the super class that we want to let other classes to inherit from.

As you can see, we only need to prefix the class with the open keyword. After that, this class can become the superclass of other classes.

Note: the keyword open can be used inside the body of a parent class as well, but this is another story and we will talk about it in the Kotlin function and property overriding section.

So far, we know how to create a class to become a super class! But now let’s see how to extend other classes to inherit from a superclass:

class ChildClass: SuperClass(){…}

As you can see, the name of the class and the way we create classes still hold true for a child class as well. The only difference is that we use a colon : after the name of the child class and invoke the super class after that as if we’re creating an object from it!

The pair of parentheses that come after the name of a superclass is the target constructor that we’re invoking! Here the assumption is that the super class didn’t have an explicit constructor and so we used an empty pair of parentheses here (as if we’re invoking the default constructor).

This is covered in greater details in the Kotlin Inheritance and Constructors sections.

Example: Implementing inheritance in Kotlin

open class Animal {
    var food = ""
    var name = ""
    var hunger = 10

    fun makeNoise() {
        println("The Animal is making a noise")
    }
    fun eat() {
        println("The Animal is eating")
    }
    fun roam() {
        println("The Animal is roaming")
    }
    fun sleep() {
        println("The Animal is sleeping")
    }
}

class Dog: Animal(){

}

fun main(){
    var dog = Dog()
    dog.eat()
    dog.roam()
    dog.name = "Cleo"

    println(dog.name)
}

How Does Inheritance Work in Kotlin?

Here the name of the superclass is Animal and the child class is Dog.

As you can see, we only made the Dog class to inherit from the Animal class! After that, we can see that the object we’ve created from the Dog class has the access to the members (properties and functions) of the Animal class as well.

Types of Inheritance in Kotlin

Inheritance has different types and models. So in this section, we will see the models of inheritance supported in Kotlin:

1- Single Level Inheritance in Kotlin

This type of inheritance involves only two classes. One of them becomes the child class and the other will be the parent class.

This is exactly like the last example we’ve seen above.

In this pattern, if we create an object from the child class and call a function, for example:

– Your program first checks the class that the object is created from and if it found the invoked function, it will load and use its body.

– But if the child class didn’t have the target function, then your program will move on to the body of the parent class to see if there’s such a function in there.

Note the order of searching for a function here! First the search starts from the child class and then if the result was negative, your program will then look into the parent class to find the target function (or any other member for that matter).

2- Multilevel Inheritance in Kotlin

The multilevel inheritance means one class becomes the parent of another one and at the same time the child class of a super class!

Let’s say you have three classes named A, B and C. Now here the class C is inheriting from the class B (so the class B is the superclass of the class C) and at the same time the class B is the child of the class A.

This way if we create an object from the class C, it will have the access to all the members of the class B and A (and of course its own members in the class C).

Here’s the order of execution when it comes to multilevel inheritance if we create an object from the class C:

– You call a function using the object and your program will first start to look into the body of the class C to see if the invoked function is declared in this body or not. If it found one, it will invoke the function and resolve the operation. This means the program won’t go into the body of the class B and A then.

– If however, your program didn’t find the target function (or any other member) in the class C, then the search continues its way into the class B to see if that class has the specified function. Now if the function is found, then it will be invoked to resolve the operation.

– But now if even the class B didn’t have the target function, the search goes one more level up to see if the class A had the target function. Now, if this class had the function, it will be invoked to resolve the operation.

The bottom line is that your program searches every class in the chain of inheritance for the target member (either property or function) to find that member. Now if the program didn’t find the member in any class, including child and parent classes, then the result will be an error at the end.

Note that the multilevel inheritance is not limited to just three classes, though! When it comes to this type of inheritance, we can have as many parent classes as we want in the chain of multilevel inheritance.

Example: creating multilevel inheritance in Kotlin

open class Grandparent {
    fun sayHiGrand(){
        println("Hello from the grandparent class")
    }
}

open class Parent: Grandparent (){
    fun sayHiParent(){
        println("Hello from the parent class")
    }
}

class Child: Parent(){
    fun sayHiChild(){
        println("Hello from the child class")
    }
}

fun main(){
    var child = Child() 

    child.sayHiChild()
    child.sayHiParent()
    child.sayHiGrand()
}

Output:

Hello from the child class

Hello from the parent class

Hello from the grandparent class

Here we have a multilevel inheritance with three classes.

We then created an object from the Child class and called three functions using this object.

Here our program ran the same order of search for the functions and so it found the sayHiChild() function in the Child class; it found the sayHiParent() function in the Parent class and finally; it found the sayHiGrand() function in the Grandparent class.

Note that any class that is going to be the parent of another class must be prefixed with the keyword open.

3- Inheritance Hierarchy in Kotlin

Inheritance hierarchy happens when two or more classes that have nothing to do with each other, both inherit from the same class.

For example, let’s say there are classes A, B and C, and now the class C and B inherit from the class A. But there’s no connection between the classes C and B.

open class A{…}

class B: A(){…}

class C: A(){…}

That’s how inheritance hierarchy works in Kotlin.

4- Multiple Inheritance in Kotlin

The multiple inheritance happens when one class is inheriting from more than one class by extending to all of them!

For example, let’s say there are three classes named A, B and C and the class C is extending to both A and B classes.

Be aware that multiple inheritance is not possible using classes in Kotlin! If we want to use multiple inheritance, we must use interfaces then. This is covered in the Kotlin Interfaces section.

Kotlin Is-A Relationship in Inheritance

The is-a relationship is a test method we use to see if a class can inherit from another class or not (logically). Basically, when you have two classes but in doubt if one can use the members of the other, run this sentence and replace the child-class and super-class with your classes:

The Child-Class is a Parent-Class.

For example, if we have two classes named Cat and Animal, then we can run the sentence as:

The Cat is an Animal.

Now if this sentence made sense to you, it means from a logical perspective, the inheritance can happen.

But if the sentence didn’t sound right, then you should not use the inheritance for the target classes.

For example, let’s say we have a class named Cat and a class named Car. Now let’s say we want to make the Cat class to inherit from the Car class because it has a set of useful methods that we want to use!

So before that, we need to run the sentence as:

The Cat is a Car.

As you can see, the sentence doesn’t sound right! For this reason, we shouldn’t apply inheritance on these two classes and instead create the methods of the Cat class in its body (even though this would be a duplicate of code, it is the right thing to do in this case).

The Has-A Relationship in Kotlin

The has-a relationship is another test method you can use to see if a class can take a property with a specific data type!

For example, let’s say we have a class named Car and another one called Steer. Now we want to add a property of type Steer inside the Car class. But before that, to make sure this is a logical thing to do, we can run a sentence using the has-a relation to see if it makes sense to add the property to the class.

For example:

Car has a Steer

As you can see, this is a sound sentence! So that means it is fine to add such property to the Car class.

But if we had a class named Animal for example and we wanted to add a property with of type Animal to a Car class, then running the has-a relationship would remind us that this is not such a good idea:

Car has an Animal

Well, cars don’t have animal in them by default! So this is not a good idea and you should avoid adding a property of type Animal to a Car class!

Example: creating a has-a relation in Kotlin

class Employee{
    var address:Address
    var firstName:String 
    var lastName:String 

    constructor(firstName:String, lastName:String, address:Address){
        this.firstName = firstName
        this.lastName = lastName
        this.address = address
    }
}
class Address{
    var city:String
    var state:String 

    constructor(city:String, state:String){
        this.city = city
        this.state = state
    }
}
fun main(){
    var address = Address("LA","CA")
    var emp = Employee("John","Doe",address)

    println(emp.firstName)
    println(emp.lastName)
    println(emp.address.city)
    println(emp.address.state)
}

Output:

John

Doe

LA

CA

As you can see, the Employee class has a property named address of type Address class. This is because it’s logical to say:

Employee has an Address

But it won’t make sense to say:

Employee is an Address

So we’ve added a property of type Address to the Employee class and then when creating an object from the Employee, we’ve set the address object for the created employee object as well.

More to Read:

Kotlin function overriding

Kotlin Upcasing and Downcasting

Kotlin Inheritance and Constructors

Facebook
Twitter
Pinterest
LinkedIn

Top Technologies