ProgramaciónDesarrollador de Kotlin

Explique las sutilezas de la visibilidad y la herencia de constructores en Kotlin: ¿cuál es la diferencia entre constructores primarios y secundarios, matices en la herencia y modificadores de visibilidad? Proporcione ejemplos de código y errores típicos.

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

En Kotlin, cualquier clase puede tener un constructor primario (especificado en la declaración de la clase) y varios constructores secundarios (a través de constructor).

  • El constructor primario no puede contener código fuera de la declaración (la lógica está en init).
  • Los constructores secundarios implementan opciones adicionales de inicialización.
  • Si el padre no tiene un constructor sin parámetros, el heredero debe invocar explícitamente su constructor.
  • Con los modificadores (private, protected, internal, public) se puede ocultar o restringir la visibilidad de los constructores.

Ejemplo con constructores primarios y secundarios:

open class Person(val name: String) { constructor(name: String, age: Int) : this(name) { // constructor secundario } } class Employee : Person { constructor(name: String) : super(name) // Se requiere super explícito }

Modificadores de visibilidad:

class Secret private constructor() { companion object { fun create() = Secret() } } val s = Secret.create() // Ok, pero Secret() - error

Matices:

  • Si una clase con un constructor primario tiene parámetros, no se puede heredar sin pasar esos parámetros.
  • Los constructores secundarios deben invocar indirecta o directamente al primario.
  • Las clases anidadas no tienen acceso al constructor privado de la clase externa.

Pregunta capciosa.

¿Es posible heredar una clase en Kotlin y no invocar su constructor primario?

Respuesta: No. En Kotlin, al heredar siempre debe ser invocado al menos un constructor del padre — ya sea el primario o uno secundario (a través de super()).

Ejemplo:

open class A(val x: Int) class B: A // Error: se requiere invocar explícitamente el constructor de A

Ejemplos de errores reales debido al desconocimiento de las sutilezas del tema.


Historia

En el equipo intentaron prohibir la creación de objetos de la clase directamente y hicieron el constructor privado. Sin embargo, olvidaron implementar el método de fábrica. Esto llevó a la imposibilidad de probar la clase sin reflexión y bloqueó CI.


Historia

Heredaron una clase con parámetros obligatorios en el constructor primario, pero no los pasaron al declarar al heredero. Esto se descubrió solo en la etapa de compilación después de una larga depuración.


Historia

Al usar constructores secundarios olvidaron que todos deben invocar al primario. Como resultado, los objetos se inicializaron sin los parámetros necesarios, lo que provocó un NullPointerException en tiempo de ejecución.