open / override
Kotlin classes are non-inheritable (final) by default. Add open to allow inheritance. Use override to override a method in a subclass. Abstract classes are defined with abstract.
Syntax
// A class marked with open can be inherited.
open class Animal(val name: String) {
open fun sound(): String = "..." // open makes this method overridable.
fun breathe() = println("Breathing") // No open = cannot be overridden.
}
// Override in a subclass.
class Dog(name: String) : Animal(name) {
override fun sound(): String = "Woof!"
}
// abstract class (cannot be instantiated)
abstract class Shape {
abstract fun area(): Double // Subclasses must implement this.
fun describe() = println("This is a shape") // Can also have concrete methods.
}
Syntax Reference
| Modifier | Description |
|---|---|
| open class | A class that allows inheritance (final by default). |
| open fun | A method that can be overridden in a subclass. |
| override fun | Overrides a method from the superclass. |
| final override fun | Prevents further overriding of the method. |
| abstract class / fun | A class that cannot be instantiated; a method that subclasses must implement. |
| super.method() | Calls a method from the superclass. |
Sample Code
// Define common behavior using an abstract class.
abstract class Shape(val color: String) {
abstract fun area(): Double
abstract fun perimeter(): Double
open fun describe() = "$color shape, area: ${"%.2f".format(area())}"
}
// Inherit using an open class.
open class Rectangle(color: String, val width: Double, val height: Double) : Shape(color) {
override fun area() = width * height
override fun perimeter() = 2 * (width + height)
override fun describe() = super.describe() + " (rectangle ${width}x${height})"
}
// Further inherit from Rectangle (open is required).
class Square(color: String, val side: Double) : Rectangle(color, side, side) {
// final override — prevents any further overriding.
final override fun describe() = "$color square, side: $side, area: ${"%.2f".format(area())}"
}
class Circle(color: String, val radius: Double) : Shape(color) {
override fun area() = Math.PI * radius * radius
override fun perimeter() = 2 * Math.PI * radius
}
fun printInfo(shape: Shape) {
println(shape.describe())
println(" perimeter: ${"%.2f".format(shape.perimeter())}")
}
fun main() {
val shapes: List<Shape> = listOf(
Rectangle("Red", 4.0, 3.0),
Square("Blue", 5.0),
Circle("Green", 3.0)
)
shapes.forEach { printInfo(it) }
println()
// Use super to call the superclass method.
val rect = Rectangle("Yellow", 6.0, 2.0)
println(rect.describe()) // Includes the result of super.describe().
}
Output
Red shape, area: 12.00 (rectangle 4.0x3.0) perimeter: 14.00 Blue square, side: 5.0, area: 25.00 perimeter: 20.00 Green shape, area: 28.27 perimeter: 18.85 Yellow shape, area: 12.00 (rectangle 6.0x2.0)
Notes
Kotlin adopts "final by default" to prevent bugs caused by unintended inheritance. When you want to allow inheritance, you must explicitly add open, which makes the design intent clear.
abstract is a contract that says "subclasses must implement this method." It is similar to an interface in that it enforces implementation, but differs in that it can hold state (fields). As a general guideline: use an abstract class for a base class with shared state, and use an interface for type contracts only.
For interface definitions, see interface. For class basics, see class / constructor.
If you find any errors or copyright issues, please contact us.