Open In App

Overriding Rules in Kotlin

Last Updated : 16 Mar, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

In any object-oriented programming language, Overriding is a feature that allows a subclass or child class to provide a specific implementation of a method that is already provided by one of its super-classes or parent classes. You decided your new class has to redefine one of the methods inherited from one of the parent classes. This is known as overriding;

If you have already programmed in Java, you will find Kotlin a more explicit language. In Java, every method is virtual by default; therefore, each method can be overridden by any derived class. In Kotlin, you would have to tag the function as being opened to redefine it. To do so, you need to add the open keyword as a prefix to the method definition, and when you redefine the method, you specifically have to mark it using the override keyword: 

Kotlin




abstract class SingleEngineAirplane protected constructor() {
  abstract fun fly()
}
  
class CesnaAirplane : SingleEngineAirplane() {
   override fun fly() {
     println("Flying a cessna")
   }
}


You can always disallow any derived classes from overriding the function by adding the final keyword in front of the method. Using the previous example, we don’t want any of the Cessna models to redefine the method:

Kotlin




class CesnaAirplane : SingleEngineAirplane() {
  final override fun fly() {
    println("Flying a cessna")
  }
}


You are not limited to functions only. Since Kotlin borrows the concept of properties from C#, you can also mark properties as virtual:

Kotlin




open class Base {
  open val property1: String
  get() = "Base::value"
}
  
class Derived1 : Base() {
  override val property1: String
  get() = "Derived::value"
}
  
class Derived2(override val property1: String) : Base() {}


You can override a val property with var if your coding logic requires this, but the reverse is not possible:

Kotlin




open class BaseB(open val propertyFoo: String) {}
  
class DerivedB : BaseB("") {
  private var _propFoo: String = ""
  override var propertyFoo: String
  get() = _propFoo
  set(value) {
    _propFoo = value
  }
}
  
fun main(args: Array<String>) {
  val baseB = BaseB("BaseB:value")
  val derivedB= DerivedB()
  derivedB.propertyFoo = "on the spot value"
  println("BaseB:${baseB.propertyFoo}")
  println("DerivedB:${derivedB.propertyFoo}")
}


There are scenarios where you need to derive from one class and at least one interface and both define and implement a method with the same name and parameters. In such cases, the inheritance rule forces you to override the method. If you create a new instance of your object and call the method that is common to the immediate parent classes, which one should the compiler link to. Therefore, you need to remove ambiguity and provide the implementation; it could use any or both the parent classes’ implementation. Imagine you have a class hierarchy for dealing with different image formats and you want to unify them with a third-party hierarchy. 

Since both class hierarchies come with a definition of the save function, you would need to override them:

Kotlin




open class Image {
  open fun save(output: OutputStream) {
    println("Some logic to save an image")
   }
 }
  
interface VendorImage {
  fun save(output: OutputStream) {
    println("Vendor saving an image")
   }
 }
  
class PNGImage : Image(), VendorImage {
  override fun save(output: OutputStream) {
    super<VendorImage>.save(output)
    super<Image>.save(output)
   }
}
  
fun main(args: Array<String>) {
  val pngImage = PNGImage()
  val os = ByteArrayOutputStream()
  pngImage.save(os)
}


The overriding is not enforced if the VendorImage interface would have not provided an implementation. Referencing the parent implementation is done via super<PARENT>, as you might have already noticed in the implementation earlier. 



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads