intermediate18 min

Interfaces and Inheritance

Kotlin's interfaces, and why classes are final unless marked open.

What you'll learn

  • Declare and implement an interface
  • Explain why Kotlin classes are final by default, and how open/override change that
  • Distinguish an interface from an abstract concept a class inherits from

Explanation

A Kotlin interface declares a contract of methods (and optionally properties) a class must implement: interface Greeter { fun greet(): String }, then class EnglishGreeter : Greeter { override fun greet() = "Hello!" } -- note the : for "implements/extends" (Kotlin uses one syntax for both) and the required override keyword, which makes it explicit and searchable which methods override something.

A genuinely distinctive Kotlin design choice: classes are final by default -- you cannot subclass a regular Kotlin class unless it's explicitly marked open. This is the opposite default from Java (where classes are open unless marked final), reflecting Kotlin's philosophy that inheritance should be a deliberate design decision, not an accident of forgetting to seal a class.

To allow subclassing, mark the class open class Animal { open fun speak() = "..." }, then a subclass can extend it and override the method: class Dog : Animal() { override fun speak() = "Woof!" } -- note the parentheses after Animal (calling its constructor) and the required override keyword again.

Guided lab

Predict: Interface implementation and open-class inheritance

KotlinNot executed
This lab does not run in your browser or on VisaSparkSchools's servers. Read the code, predict what it does, then reveal the real expected output.

Read this program and predict exactly what it prints.

interface Greeter {
    fun greet(): String
}

open class Animal(val name: String) {
    open fun speak() = "..."
}

class Dog(name: String) : Animal(name), Greeter {
    override fun speak() = "Woof!"
    override fun greet() = "$name says hi"
}

fun main() {
    val dog = Dog("Rex")
    println(dog.speak())
    println(dog.greet())
}

Stuck? Get a hint.

Common mistakes

  • Trying to subclass a regular Kotlin class and being surprised by a compile error -- classes are final by default; the base class must be marked `open`.
  • Forgetting the `override` keyword when implementing an interface method or overriding an open method -- Kotlin requires it explicitly, unlike some languages where it's optional.
  • Confusing interface implementation with class inheritance -- both use `:` in Kotlin, but a class can implement multiple interfaces while extending only one base class.

Knowledge check

Knowledge check

1. Are Kotlin classes subclassable by default?
2. What keyword must you use when implementing an interface method or overriding an open method?
3. Can a Kotlin class implement more than one interface?

Takeaway

Kotlin classes are final by default -- mark a base class `open` (and its methods `open`) deliberately to allow subclassing, and always use `override` explicitly.

Summary

Interfaces declare a contract implemented with `:` and `override`; classes are final unless marked `open`, reflecting Kotlin's deliberate-inheritance philosophy.

References

Your notes

Notes save automatically.

Finished this lesson?

Mark it complete to track your progress and schedule a future review.