Historia de la pregunta:
La anulación de métodos es la base de la OOP, pero en Java originalmente override no era obligatorio. Kotlin es un lenguaje de tipado estricto que ha introducido el uso obligatorio de override para aumentar la claridad del código y evitar errores accidentales durante la herencia.
Problema:
Sin una indicación clara de override, es fácil cometer errores al describir una interfaz/clase: errar en el nombre, tipo o modificador. El programa no fallará, pero la anulación esperada no será efectiva. Kotlin aborda este problema de manera radical.
Solución:
En Kotlin, para que un método pueda ser anulado, debe declararse como open (o abstract/interface). Para anular, es obligatorio escribir override. Si las firmas no coinciden, se produce un error de compilación. Esto previene la mayoría de los errores clásicos de Java.
Ejemplo de código:
open class Base { open fun greet() { println("¡Hola!") } } class Child : Base() { override fun greet() { println("¡Hola!") } }
Características clave:
¿Se puede anular accidentalmente una función si se olvida el override?
No. Si omites override, el método declarado se considerará un nuevo método de la clase y no habrá anulación; el compilador mostrará un error si open está presente en el método base.
Ejemplo de código:
open class A { open fun test() {} } class B : A() { fun test() {} // no anula! Igual que test2() }
¿Pueden sus métodos tener una visibilidad más estricta que la del padre?
No. No se puede restringir el ámbito de visibilidad de un método anulado. Por ejemplo, si el método base es public, la anulación override no puede ser private/protected/internal. El compilador mostrará un error.
¿Puede un componente override ser final?
¡Sí! Si no deseas más anulaciones, añade final:
class D : Base() { final override fun greet() { //... } }
En Java:
public class Parent {void foo(){} } public class Child extends Parent {void foo(int x){} }
Se espera una anulación, pero en realidad es una sobrecarga. Las llamadas no se dirigen al método correcto.
Ventajas:
Desventajas:
En Kotlin:
open class Parent { open fun foo() {} } class Child : Parent() { override fun foo() { /*...*/ } }
Ventajas:
Desventajas: