Intermediate 8 min readKotlin 2.0

Kotlin Inheritance โ€” open, override, and super

Kotlin classes are final by default. Use open to allow inheritance. Subclasses override functions explicitly with override.

What You Will Learn

  • Why classes are final by default
  • Use open to enable inheritance
  • Override properties and functions
  • Call super in overrides
  • Use abstract classes

open Classes

By default, Kotlin classes cannot be inherited. Add open to allow subclassing.

open and override

kotlin
open class Animal(val name: String) {
    open fun sound(): String = "..."
    fun describe() = "$name says: ${sound()}"
}

class Dog(name: String) : Animal(name) {
    override fun sound() = "Woof"
}

class Cat(name: String) : Animal(name) {
    override fun sound() = "Meow"
}

fun main() {
    val animals = listOf(Dog("Rex"), Cat("Whiskers"), Dog("Buddy"))
    for (a in animals) println(a.describe())
}
Output
Rex says: Woof Whiskers says: Meow Buddy says: Woof

open class Animal can be subclassed. open fun sound() can be overridden. override fun sound() in the subclass provides a new implementation.

Best Practice: Keep classes final (default) unless you specifically design them for inheritance. This is effective Kotlin style.

Abstract Classes

Abstract classes cannot be instantiated. They define a contract that subclasses must implement.

abstract class

kotlin
abstract class Shape {
    abstract fun area(): Double
    fun describe() = "Area: ${"%.2f".format(area())}"
}

class Rectangle(val w: Double, val h: Double) : Shape() {
    override fun area() = w * h
}

class Circle(val r: Double) : Shape() {
    override fun area() = Math.PI * r * r
}

fun main() {
    val shapes: List<Shape> = listOf(Rectangle(4.0, 5.0), Circle(3.0))
    shapes.forEach { println(it.describe()) }
}
Output
Area: 20.00 Area: 28.27

abstract fun area() has no implementation โ€” subclasses must provide one. describe() is concrete and reuses area().

Calling super

Use super to call the parent class implementation.

super keyword

kotlin
open class Vehicle(val brand: String) {
    open fun info() = "Brand: $brand"
}

class Car(brand: String, val model: String) : Vehicle(brand) {
    override fun info() = "${super.info()}, Model: $model"
}

fun main() {
    val car = Car("Toyota", "Corolla")
    println(car.info())
}
Output
Brand: Toyota, Model: Corolla

super.info() calls Vehicle.info(). The Car then appends additional information.

Practice Exercise

Exercisepredict output

What prints? open class Base { open fun greet() = "Hello from Base" } class Child : Base() { override fun greet() = super.greet() + " and Child" } fun main() { println(Child().greet()) }

Quick Quiz

Quick Quiz

Why are Kotlin classes final by default?

Frequently Asked Questions

Related Tutorials

Last updated: 2026-05-01Kotlin 2.0

Written by KotlinGuide Editorial Team ยท Reviewed by KotlinGuide Technical Review