ProgramaciónDesarrollador Kotlin/Java

¿Cómo está implementada la herencia de constructores en Kotlin, cómo funciona la llamada al constructor super, y qué trampas existen al combinar constructores primarios y secundarios? Proporcione ejemplos para diferentes casos, explique la diferencia con Java.

Supere entrevistas con el asistente de IA Hintsage

Respuesta

En Kotlin, una clase puede tener un constructor primario y tantos constructores secundarios como se deseen. La diferencia con Java es que en Kotlin el constructor primario se declara en la cabecera de la clase y puede contener parámetros y modificadores. Los constructores secundarios siempre deben llamar a otro constructor secundario, al constructor primario o al constructor de la superclase (a través de la palabra clave super).

Características clave:

  • Si la superclase tiene un constructor primario con parámetros obligatorios, la clase derivada siempre debe llamarlo explícitamente a través de : super(...).
  • En el constructor secundario, la clase base se llama a través de super(...) o de otro constructor secundario/primario.
  • No se permite un conflicto de inicialización: todos los campos siempre deben estar correctamente inicializados.

Ejemplo de uso con herencia:

open class A(val a: Int) { constructor(a: Int, str: String) : this(a) { println("Secundario en A: $str") } } class B : A { constructor(a: Int) : super(a) { println("Secundario en B") } constructor(a: Int, s: String) : super(a, s) { println("Secundario #2 en B") } }

¿En qué se diferencia el enfoque de Java?:

  • En Kotlin no se puede NO llamar al constructor de la superclase.
  • El constructor primario siempre inicializa los parámetros base y puede ser implícito.

Pregunta capciosa

¿Se puede en Kotlin crear una clase derivada SIN llamar explícitamente al constructor de la superclase, si en la clase base solo hay un constructor definido?

Respuesta: No, a diferencia de Java, en Kotlin la llamada al constructor de la superclase es obligatoria y se indica explícitamente en la "cabeza" de la clase o después de la palabra clave : super().

Ejemplo de error:

open class Base(val x: Int) class Derived : Base // ¡Error de compilación!

Ejemplos de errores reales debido a la falta de conocimiento de los matices del tema


Historia

En un proyecto de microservicios, después de migrar a Kotlin, olvidaron la indicación explícita del constructor padre: el constructor de la superclase con un parámetro obligatorio no fue llamado, el servicio no compiló, y se necesitó refactorizar las firmas.


Historia

Un proyecto de Android tenía una profunda jerarquía (Activity → BaseActivity → CustomActivity), la adición de un constructor secundario perdía parámetros, al final se llamaba al constructor base incorrecto y parte de los campos quedaba null — la aplicación caía en tiempo de ejecución con NPE.


Historia

En un código de biblioteca abierto, un constructor secundario en la clase derivada evitó accidentalmente el constructor primario, lo que condujo a dos ramas diferentes de inicialización: a veces el campo se inicializaba, a veces no. El error fue encontrado solo después de mucho tiempo debido a complejos informes de errores.