Kotlin classes and members are final by default. Add open when inheritance or overriding is an intentional part of the design. Mark both the class and each overridable property or method explicitly; otherwise subclasses cannot extend or replace them. section 4.1.2
Allowing selected overrides
open class RichButton : Clickable { fun disable() { /* ... */ } open fun animate() { /* ... */ } override fun click() { /* ... */ } } class ThemedButton : RichButton() { override fun animate() { /* ... */ } override fun click() { /* ... */ } } Here, RichButton is inheritable, animate can be replaced, and disable remains unavailable for overriding. Because click overrides a member from Clickable, it is open to further subclasses unless explicitly marked final. section 4.1.2
Use the modifier with these boundaries in mind:
- Mark a class open before declaring subclasses; mark every property or method intended for overriding open as well. section 4.1.2
- Use final on an overriding member when its implementation must stop the override chain: final override fun click() { /* ... */ }. section 4.1.2
- Do not expect open to make extension functions polymorphic. Extensions are resolved from the variable's declared type, unlike overridden member functions. section 3.3.4
- Final-by-default declarations also support more reliable smart casts because subclasses cannot replace a final property with a custom accessor. section 4.1.2
Listing 4.8 Declaring an open class with an open method
open class RichButton : Clickable { #1
fun disable() { /* ... */ } #2
open fun animate() { /* ... */ } #3
override fun click() { /* ... */ } #4
}
Inspect the compact declaration showing an open class, a non-overridable member, an open method, and an overridden interface member. section 4.1.2
