Kotlin

Kotlin Inheritance

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.

Kotlin
// 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 Animal class is open, making it inheritable.
  • The Dog class extends Animal using the : symbol.
  • The Dog class gets access to the eat() function from Animal.
  • The bark() function is specific to Dog.

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:

Kotlin
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 Animal class has a primary constructor with a name parameter.
  • The Dog class calls the Animal constructor using : Animal(name).
  • When we create a Dog object, we pass a name that is used in both eat() and bark().

Overriding Methods in Kotlin

Kotlin allows child classes to modify or override methods from the parent class using the override keyword.

Kotlin
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 in Animal is open, allowing it to be overridden.
  • Dog provides its own implementation using override.
  • Now, when makeSound() is called on Dog, 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:

Kotlin
'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.

Kotlin
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.

Kotlin
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.

Kotlin
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 open to make a class inheritable.
  • Override methods with override.
  • Use super to call the parent method.
  • Use abstract for mandatory implementations.

By mastering Kotlin inheritance, you can build scalable, maintainable, and clean applications.

Restrictions for public API inline functions

Restrictions For Public API Inline Functions in Kotlin and How to Avoid Them

Kotlin’s inline functions offer powerful performance optimizations, but when used in public APIs, they come with specific restrictions. Understanding these limitations helps ensure compatibility, maintainability, and adherence to best coding practices.  In this blog, we’ll explore the restrictions for public API inline functions and discuss ways to work around them. Restrictions for public API inline...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
Kotlin OOP Essentials

Kotlin OOP Essentials: Everything About Classes, Properties & Methods

Kotlin is a powerful programming language that fully supports Object-Oriented Programming (OOP). If you’re diving into Kotlin OOP Essentials, understanding classes, properties, and methods is crucial. This guide will break down these core concepts in a simple and engaging way, ensuring you master Kotlin’s OOP capabilities. Classes Classes serve as the fundamental building blocks in...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
Type Erasure

Understanding Type Erasure in Kotlin Generics

Generics are a powerful feature in Kotlin that allow us to write flexible and reusable code. However, one of the key aspects to understand when working with generics is Type Erasure. If you’ve ever tried to inspect a generic type at runtime and found unexpected behavior, you’ve likely encountered type erasure in Kotlin generics. In...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
fully and partially checked exceptions

How Java Handles Fully and Partially Checked Exceptions: A Deep Dive

Exception handling is a crucial part of Java programming. It ensures that programs can gracefully handle unexpected situations without crashing. Java categorizes exceptions into checked and unchecked exceptions, but a lesser-known distinction exists within checked exceptions: fully and partially checked exceptions. In this blog, we’ll explore how Java handles fully and partially checked exceptions, using...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
crossinline modifier

Why Does Kotlin Have crossinline Modifier? Exploring the Need for This Modifier

Kotlin provides several function modifiers that improve code safety, performance, and flexibility. One such modifier is crossinline. If you’ve ever used inline functions in Kotlin, you might have come across crossinline but wondered why it’s needed. In this blog, we’ll break it down step by step, explaining why Kotlin has the crossinline modifier, when to...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
Type Checks in Kotlin

Understanding Type Checks in Kotlin: How is and !is Work

Type checking is a fundamental concept in programming, and Kotlin makes it simple with is and !is. These operators help you check whether an object is of a certain type and allow you to write safe and concise code. In this post, we’ll break down how type checks (is and !is) in Kotlin work, with...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
capturing mutable variables in Kotlin lambdas

Capturing Mutable Variables in Kotlin Lambdas: Why Kotlin Developers Struggle

Kotlin is a powerful and expressive language, but it introduces some challenges when dealing with mutable variables inside lambdas. If you’ve ever encountered issues while capturing mutable variables in Kotlin lambdas, you’re not alone. Many developers struggle with this concept, leading to unexpected behavior, performance concerns, and even compiler errors. In this blog post, we’ll...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
Non-Local Returns

Understanding Non-Local Returns in Kotlin: A Deep Dive into Lambda Behavior

Kotlin is known for its expressive and concise syntax, but one of the lesser-understood features is non-local returns in Kotlin lambda. This concept plays a crucial role in handling control flow inside lambda expressions. In this blog, we will explore what non-local returns are, how they work, and when to use them effectively. What Are...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
Capturing Non-Final Variables in Kotlin Lambdas

Workarounds for Capturing Non-Final Variables in Kotlin Lambdas

Kotlin lambdas are powerful, but they come with a constraint: they can only capture final (effectively immutable) variables from their enclosing scope. This can be a challenge when you need to modify a variable inside a lambda. In this blog, we will explore why this restriction exists and the workarounds you can use to capture...

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here
error: Content is protected !!