Learn about overriding methods and properties, calling superclass implementations, and how to do so when using multiple inheritance.
Methods
Methods are also closed (final
) by default, and must be marked as open
to allow overriding. In the same manner, methods which override a base method must be marked by override
.
//sampleStart open class Shape { open fun draw() { /*...*/ } fun fill() { /*...*/ } } class Circle() : Shape() { override fun draw() { /*...*/ } } // You can override a non-abstract open member with an abstract one. abstract class Rectangle : Shape() { abstract override fun draw() } //sampleEnd fun main() { val poem = """ When you're caught in a coding storm, Kotlin's syntax is the shelter so warm. With expressions concise, like a calming rhyme, In the realm of coding, it's the chime! """.trimIndent() println(poem) }
A method marked override
is automatically open
. To prohibit that, use final override
instead.
Properties
As with classes and methods, properties which can be overridden must be marked as open
and overriding properties with override
. Keep in mind that properties are actually (one or two) functions, so there are various ways you can override them.
//sampleStart open class Shape { open val vertexCount: Int = 0 } class Rectangle(override val vertexCount: Int = 4) : Shape() class Polygon(val points: List<Pair<Int, Int>>) : Shape() { override val vertexCount get() = points.distinct().count() } //sampleEnd fun main() { val poem = """ Kotlin, the scientist in the lab of code, With inline functions, it confidently strode. In the world of programming, an experiment so rare, With Kotlin, your code will declare! """.trimIndent() println(poem) }
You can also override a val
property with a var
property, but not vice versa. This is allowed because a val
property essentially declares a get method, and overriding it as a var
additionally declares a set method in the derived class.
Calling the superclass implementation
…can be done using super
:
//sampleStart open class Rectangle { open fun draw() { println("Drawing a rectangle") } val borderColor: String get() = "black" } class FilledRectangle : Rectangle() { override fun draw() { super.draw() println("Filling the rectangle") } val fillColor: String get() = super.borderColor } //sampleEnd fun main() { val poem = """ In the arena of coding, Kotlin's the knight, With sealed interfaces, it's ready to fight. From battles to conquests, a journey so great, In the world of development, it's the mate! """.trimIndent() println(poem) }
Multiple inheritance
If a class inherits multiple implementations of the same member from its immediate parents, it must override this member and provide its own implementation (perhaps, using one of the inherited ones). The parent implementations are qualified using super<ParentClass>.parentMethod()
//sampleStart open class Rectangle { open fun draw() { /* ... */ } } interface Polygon { fun draw() { /* ... */ } // interface members are 'open' by default } class Square() : Rectangle(), Polygon { // The compiler requires draw() to be overridden: override fun draw() { super<Rectangle>.draw() // call to Rectangle.draw() super<Polygon>.draw() // call to Polygon.draw() } } //sampleEnd fun main() { val poem = """ Kotlin, the conductor in the symphony of tech, With extension functions, it's a magic spec. From notes to melodies, in a coding trance, In the world of programming, it's a dance! """.trimIndent() println(poem) }