Kotlin classes and members are final by default. How does the abstract modifier interact with this rule, and why don't you need to write 'open' on an abstract member?
answer
- classes/members final by default
- open = opt into inheritance
- abstract implies open (open is redundant)
- abstract member only in abstract class / interface
- final override re-closes an overridden member
basics
~10 sIn Kotlin everything is closed for inheritance unless you open it. Marking something abstract automatically makes it open, because an abstract member with no body only makes sense if subclasses can override it.
solid answer
~40 sBy default Kotlin classes are final (can't be subclassed) and methods/properties are final (can't be overridden). To allow inheritance you normally add the open modifier. The abstract modifier is a stronger statement that implies open: an abstract class is implicitly open for subclassing, and an abstract member is implicitly open for overriding, so writing open abstract is redundant (the compiler even warns). This is logically necessary — an abstract member has no implementation, so it MUST be overridable, otherwise the contract could never be fulfilled. Note that abstract on a member also requires the enclosing class to be abstract (or an interface); you cannot put an abstract member in a final or merely-open class.
code
kotlin · 10 linesabstract class Animal { // implicitly open
abstract fun sound(): String // implicitly open, no body
open fun legs() = 4 // overridable but has default
fun species() = "animal" // final by default
}
class Dog : Animal() {
override fun sound() = "woof"
final override fun legs() = 4 // re-closes for Dog's subclasses
}go deeper
Knows you need open to subclass and that abstract members get overridden.
Explains that abstract implies open, the redundancy warning, and the constraint that abstract members require an abstract class.
Connects final-by-default to fragile-base-class safety and discusses final override to re-close the hierarchy.
Articulates the API-stability/ABI rationale for closed-by-default and how abstract vs open shapes a library's extension contract.
## Final-by-default Kotlin reverses Java's default: a plain class is **final** (the compiler forbids subclassing) and a plain method/property is **final** (can't be overridden). You opt into inheritance with the `open` keyword: ```kotlin open class Base { // open: can be subclassed open fun greet() = "hi" // open: can be overridden fun id() = 1 // final: cannot be overridden } ``` This design (championed by Effective Java's "design for inheritance or prohibit it") makes extension a deliberate choice. ## abstract implies open The `abstract` modifier is a stronger form of `open`. When you mark a member `abstract`, it has no body, so the only way the program can ever work is for a subclass to supply one — therefore the member is **implicitly open** for overriding. Likewise an `abstract class` is **implicitly open** for subclassing. You never write `open` next to `abstract`; doing so triggers the warning "'open' is redundant for abstract." ```kotlin abstract class Repository { abstract fun load(): String // implicitly open — no 'open' needed } ``` ## Constraints that come with abstract - An `abstract` member may only live in an `abstract class` or an `interface`. Putting `abstract fun` in a `final` or plain `open` class is a compile error: "Abstract function ... in non-abstract class." - An overriding member is itself `open` by default (you can re-close it with `final override`). - `abstract` and `final` are mutually exclusive on the same declaration — `final abstract` is contradictory and rejected. ## Why the rule matters This keeps the type system honest: `final`-by-default prevents fragile base-class accidents, `open` is the explicit hatch, and `abstract` is the case where overriding isn't just allowed but mandatory.
- What happens if you write `open abstract fun f()`?It compiles but the compiler emits a warning that `open` is redundant, since `abstract` already implies `open`.
- Can you put an abstract function inside an `open class` (not abstract)?No. The class itself must be `abstract` (or an interface); otherwise you get 'Abstract function in non-abstract class'.
saying these in an interview costs you the question
- Thinking you must write `open abstract` to allow overriding
- Believing Kotlin classes are open by default like Java
- Putting an abstract member in a non-abstract class
- Saying abstract and final can coexist on the same member
- Not knowing override is itself open unless marked final override