En cualquier lenguaje de programación orientado a objetos, Overriding es una función que permite que una subclase o clase secundaria proporcione una implementación específica de un método que ya proporciona una de sus superclases o clases principales. Decidiste que tu nueva clase tiene que redefinir uno de los métodos heredados de una de las clases principales. Esto se conoce como anulación;
Si ya has programado en Java, encontrarás en Kotlin un lenguaje más explícito. En Java, todos los métodos son virtuales por defecto; por lo tanto, cada método puede ser anulado por cualquier clase derivada. En Kotlin, tendría que etiquetar la función como abierta para redefinirla. Para hacerlo, debe agregar la palabra clave open como prefijo a la definición del método y, cuando redefina el método, debe marcarlo específicamente con la palabra clave override:
Kotlin
abstract class SingleEngineAirplane protected constructor() { abstract fun fly() } class CesnaAirplane : SingleEngineAirplane() { override fun fly() { println("Flying a cessna") } }
Siempre puede impedir que las clases derivadas anulen la función agregando la palabra clave final delante del método. Usando el ejemplo anterior, no queremos que ninguno de los modelos Cessna redefina el método:
Kotlin
class CesnaAirplane : SingleEngineAirplane() { final override fun fly() { println("Flying a cessna") } }
No está limitado solo a las funciones. Dado que Kotlin toma prestado el concepto de propiedades de C#, también puede marcar propiedades como virtuales:
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() {}
Puede anular una propiedad val con var si su lógica de codificación lo requiere, pero lo contrario no es posible:
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}") }
Hay escenarios en los que necesita derivar de una clase y al menos una interfaz y definir e implementar un método con el mismo nombre y parámetros. En tales casos, la regla de herencia lo obliga a anular el método. Si crea una nueva instancia de su objeto y llama al método que es común a las clases primarias inmediatas, a cuál debe vincularse el compilador. Por lo tanto, debe eliminar la ambigüedad y proporcionar la implementación; podría usar cualquiera o ambas implementaciones de las clases principales. Imagine que tiene una jerarquía de clases para manejar diferentes formatos de imagen y desea unificarlos con una jerarquía de terceros.
Dado que ambas jerarquías de clases vienen con una definición de la función de guardar, deberá anularlas:
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) }
La anulación no se aplica si la interfaz VendorImage no hubiera proporcionado una implementación. La referencia a la implementación principal se realiza a través de super<PARENT>, como ya habrá notado en la implementación anterior.
Publicación traducida automáticamente
Artículo escrito por eralokyadav2019 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA