Open Classes
In this page:
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
open class Animal(val name: String) {
fun describe() = "Animal: $name"
}
fun main() {
val animal = Animal("Generic")
println(animal.describe())
}
Login to try C/C++/Java/PHP code in the editor
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
open class Animal(val name: String)
class Dog(name: String) : Animal(name)
fun main() {
val dog = Dog("Rex")
println("Dog name: ${dog.name}")
}
Login to try C/C++/Java/PHP code in the editor
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
open class Animal(val name: String) {
open fun sound(): String = "..."
}
class Dog(name: String) : Animal(name) {
override fun sound(): String = "Woof"
}
fun main() {
val dog = Dog("Rex")
println("${dog.name} says ${dog.sound()}")
}
Login to try C/C++/Java/PHP code in the editor
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
open class Counter {
open var count: Int = 0
protected set
open fun increment() {
count++
}
}
class StepCounter : Counter() {
override fun increment() {
count += 2
}
}
fun main() {
val counter = StepCounter()
counter.increment()
counter.increment()
println("Count: ${counter.count}")
}
Login to try C/C++/Java/PHP code in the editor
- Trying to subclass a regular class and getting a compiler error, forgetting that Kotlin classes are
final(non-inheritable) unless markedopen. - Marking a class
openbut forgetting its individual members also needopenbefore a subclass can override them. - Assuming
openclasses are inherently less safe; being explicit about inheritance is actually a deliberate Kotlin design choice for safety.
- Kotlin classes are
finalby default, meaning they cannot be subclassed unless explicitly markedopen. - Individual members (functions, properties) also need
openbefore 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: