Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

In Kotlin, an open function is a class member function explicitly marked with the open modifier, permitting subclasses to override its implementation. Because Kotlin enforces a closed-by-default inheritance model where all classes and methods are implicitly final, the open keyword is strictly required to enable method overriding and dynamic dispatch.

Syntax and Implementation

To declare an open function, place the open keyword before the fun declaration. The subclass must then use the override modifier to provide a new implementation.
open class BaseClass {
    // Explicitly marked open; can be overridden
    open fun executeTask() {
        println("Base implementation")
    }

    // Implicitly final; cannot be overridden
    fun standardTask() {
        println("Final implementation")
    }
}

class DerivedClass : BaseClass() {
    // Requires the override modifier
    override fun executeTask() {
        super.executeTask() // Optional: calling the base implementation
        println("Derived implementation")
    }
    
    // Attempting to override standardTask() will result in a compilation error
}

Technical Rules and Behavior

  • Enclosing Class Requirement: An open function can only be overridden if the enclosing class is also marked open (or abstract). A subclass cannot inherit from a final class, rendering open functions inside a final class functionally meaningless.
  • Override Propagation: When a subclass overrides an open function, the overriding function itself remains implicitly open to further subclasses down the inheritance hierarchy.
  • Sealing an Override: To prevent further overriding in deeper subclasses, the final modifier must be explicitly combined with override.
open class SubClass : BaseClass() {
    final override fun executeTask() {
        // Cannot be overridden by classes inheriting from SubClass
    }
}
  • Interface Members: Functions declared within an interface are implicitly open. Applying the open modifier to interface functions is redundant and generates a compiler warning.
  • Extension Functions: Top-level extension functions are resolved statically based on the declared type and cannot be marked open or overridden. However, member extension functions (extension functions declared inside a class) can be marked open and overridden in subclasses. For member extensions, the dispatch is virtual with respect to the dispatch receiver (the class instance) but remains static with respect to the extension receiver.
open class BaseDispatcher {
    // Member extension function marked open
    open fun String.process() {
        println("Base processing: $this")
    }
    
    fun dispatch(value: String) {
        value.process() // Virtual dispatch on BaseDispatcher, static on String
    }
}

class DerivedDispatcher : BaseDispatcher() {
    // Overriding the member extension function
    override fun String.process() {
        println("Derived processing: $this")
    }
}
  • Constructor Invocation: Calling an open function from within a base class constructor is considered unsafe. If a derived class overrides the function, the overridden implementation will execute before the derived class’s properties are fully initialized, which can lead to NullPointerExceptions or inconsistent state.
Master Kotlin with Deep Grasping Methodology!Learn More