← Back to Kotlin Course | Chapter 7: Inheritance & Interfaces | Lesson 1 of 7

Open Classes

An open class is one that has given permission to be extended into new, more specific classes; regular classes refuse this by default.
Syntax
kotlin
open class BaseClass(val property: Type) {
    open fun method() { }
}

class SubClass(property: Type) : BaseClass(property)

Classes Are Final by Default

Unlike Java, a Kotlin class cannot be subclassed unless it is explicitly marked open. This deliberate default prevents accidental fragile inheritance hierarchies.

Example: Classes Are Final by Default

markup
open class Animal(val name: String) {
    fun describe() = "Animal: $name"
}

// Entry point: execution of the program starts here
fun main() {
    // Declare a read-only variable `animal`, set to `Animal("Generic")`
    val animal = Animal("Generic")
    // Print `animal.describe()` to the console, with a trailing newline
    println(animal.describe())
}

Subclassing an Open Class

A class marked open can be extended with class Sub : Base(constructorArgs), which calls the base class's constructor as part of creating the subclass instance.

Example: Subclassing an Open Class

markup
open class Animal(val name: String)

// Define a class `Dog`
class Dog(name: String) : Animal(name)

// Entry point: execution of the program starts here
fun main() {
    // Declare a read-only variable `dog`, set to `Dog("Rex")`
    val dog = Dog("Rex")
    // Print "Dog name: ${dog.name}" to the console, with a trailing newline
    println("Dog name: ${dog.name}")
}

Open Members

Marking a class open only allows subclassing; each individual function or property that should be overridable must also be marked open separately.

Example: Open Members

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

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

// Entry point: execution of the program starts here
fun main() {
    // Declare a read-only variable `dog`, set to `Dog("Rex")`
    val dog = Dog("Rex")
    // Print "${dog.name} says ${dog.sound()}" to the console, with a trailing newline
    println("${dog.name} says ${dog.sound()}")
}

Why Closed by Default Helps

Requiring open explicitly forces the class author to think about which parts of a class are safe to extend, avoiding accidental behavior changes in subclasses that a truly closed design would prevent entirely.

Example: Why Closed by Default Helps

markup
open class Counter {
    open var count: Int = 0
        protected set

    open fun increment() {
        count++
    }
}

// Define a class `StepCounter`
class StepCounter : Counter() {
    override fun increment() {
        count += 2
    }
}

// Entry point: execution of the program starts here
fun main() {
    // Declare a read-only variable `counter`, set to `StepCounter()`
    val counter = StepCounter()
    counter.increment()
    counter.increment()
    // Print "Count: ${counter.count}" to the console, with a trailing newline
    println("Count: ${counter.count}")
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Trying to subclass a regular class and getting a compiler error, forgetting that Kotlin classes are final (non-inheritable) unless marked open.
  2. Marking a class open but forgetting its individual members also need open before a subclass can override them.
  3. Assuming open classes are inherently less safe; being explicit about inheritance is actually a deliberate Kotlin design choice for safety.
Chapter Summary
  • Kotlin classes are final by default, meaning they cannot be subclassed unless explicitly marked open.
  • Individual members (functions, properties) also need open before a subclass can override them.
  • This 'closed by default' design avoids fragile base class problems common in languages where everything is inheritable by default.
  • A subclass is declared with class Sub : Base(...), calling the base class's constructor.
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.