Command Palette

Search for a command to run...

La palabra clave super: Acceso a la Clase Padre

Aprende a usar super para acceder al constructor, métodos y propiedades de la clase padre en JavaScript moderno.

Lectura: 16 min
Nivel: Intermedio

TL;DR - Resumen rápido

  • super permite acceder al constructor de la clase padre
  • super permite llamar a métodos de la clase padre
  • super permite acceder a propiedades de la clase padre
  • super debe usarse en la primera línea del constructor de la clase hija
  • super permite extender funcionalidad de la clase padre
  • super es obligatorio en el constructor de la clase hija

Introducción a super

La palabra clave super es fundamental en la herencia de clases de JavaScript. Te permite acceder al constructor y métodos de la clase padre desde una clase hija, facilitando la extensión de funcionalidad mientras mantienes el comportamiento original. super actúa como un puente entre la clase hija y la clase padre, permitiendo reutilizar código y construir jerarquías de clases organizadas.

Hay tres usos principales de super: super() para llamar al constructor del padre (obligatorio si defines constructor en la clase hija), super.metodo() para llamar métodos del padre, y super.propiedad para acceder a getters y setters del padre. Cada uno tiene sus propias reglas y casos de uso que exploraremos en detalle.

Requisito: extends

super solo puede usarse dentro de clases que heredan de otra clase usando extends. Intentar usar super en una clase sin herencia o en funciones regulares resulta en un SyntaxError. Es exclusivo del contexto de herencia de clases.

super() en el Constructor

Cuando una clase hija define su propio constructor, debe llamar a super() antes de poder usar this. La llamada super() invoca al constructor de la clase padre, pasándole los argumentos necesarios para inicializar las propiedades heredadas. Esta es una regla estricta del lenguaje: no puedes acceder a this hasta que super() haya sido llamado.

super-constructor.js
Loading code...

Este ejemplo muestra el uso correcto de super() en el constructor. La clase Auto hereda de Vehiculo y llama a super(marca, año) como primera línea del constructor. Esto inicializa las propiedades marca, año y kilometraje del padre. Solo después de esta llamada puede usar this para inicializar sus propias propiedades puertas y tipo. El código comentado muestra el error que ocurre si intentas usar this antes de super().

Reglas estrictas de super()

Las reglas de super() son inflexibles: debe ser la primera declaración ejecutable en el constructor, solo puede llamarse una vez, y no puedes usar this antes de llamarlo. Estas reglas existen porque el objeto aún no está completamente inicializado hasta que el constructor del padre ha corrido. Violar cualquiera de estas reglas resulta en un ReferenceError en tiempo de ejecución.

super() es obligatorio

Si defines un constructor en una clase hija, DEBES llamar super() antes de usar this. Olvidarlo o llamarlo después de usar this resulta en un ReferenceError: "Must call super constructor in derived class before accessing 'this'".

super en Métodos

La sintaxis super.metodo() te permite llamar métodos de la clase padre desde métodos de la clase hija. Esto es especialmente útil cuando sobrescribes un método pero quieres mantener parte de la funcionalidad original. En lugar de duplicar código, llamas al método del padre y luego agregas tu comportamiento adicional, siguiendo el principio DRY (Don't Repeat Yourself).

super-metodos.js
Loading code...

Este ejemplo muestra cómo extender métodos del padre. La clase Gerente sobrescribe calcularBono(), pero en lugar de reemplazar completamente la lógica, llama a super.calcularBono() para obtener el bono base (10%) y luego agrega un bono adicional para gerentes (5%), resultando en un 15% total. Esto reutiliza la lógica del padre y la extiende con comportamiento específico de la clase hija.

Cuándo usar super.metodo()

Usa super.metodo() cuando el método del padre hace algo útil que quieres conservar y extender. No lo uses si necesitas reemplazar completamente la funcionalidad (en ese caso, simplemente sobrescribe el método sin llamar a super). El patrón común es llamar super.metodo() al inicio o al final de tu método, dependiendo de si quieres que el comportamiento del padre ocurra antes o después de tu lógica.

Extender, no duplicar

Usar super.metodo() te permite extender la funcionalidad del padre sin duplicar código. Es especialmente valioso en jerarquías profundas donde cada nivel agrega comportamiento incremental sobre el nivel anterior.

super en Getters y Setters

super funciona perfectamente con getters y setters, permitiéndote extender o modificar el comportamiento de acceso a propiedades de la clase padre. Puedes llamar a super.propiedad para invocar el getter del padre, o asignar super.propiedad = valor para invocar el setter del padre. Esto es útil cuando quieres agregar validación adicional o transformar valores antes o después de usar la lógica del padre.

super-getters-setters.js
Loading code...

Este ejemplo muestra cómo extender getters y setters del padre. La clase Estudiante sobrescribe el getter nombre para agregar el prefijo "Estudiante:" llamando a super.nombre. El setter edad agrega validación adicional (mínimo 16 años) y luego llama a super.edad = value para que la validación del padre (0-150) también se ejecute. Esto permite agregar capas de validación sin duplicar código.

Validación en capas

Usar super en setters te permite crear validaciones en capas: la clase padre valida reglas generales y cada clase hija puede agregar validaciones más específicas. Esto mantiene la separación de responsabilidades y evita duplicación de lógica de validación.

super en Métodos Estáticos

super también funciona en métodos estáticos de clases. Dentro de un método estático, super.metodo() llama al método estático del padre. Esto es útil para crear jerarquías de utilidades o funciones factory que se construyen sobre funcionalidad del padre, manteniendo el código organizado y reutilizable.

super-metodos-estaticos.js
Loading code...

Este ejemplo muestra super en métodos estáticos. La clase Rectangulo sobrescribe el método estático descripcion() y extiende el mensaje del padre. El método estático validarDimensiones() usa super.validarDimension() para validar cada dimensión usando la lógica del padre. El método factory crear() combina validación y construcción de objetos, reutilizando métodos estáticos del padre.

Factory methods

Los métodos estáticos con super son perfectos para implementar factory methods que validan datos antes de crear instancias. Puedes reutilizar validaciones del padre mientras agregas validaciones específicas de cada subclase.

super vs this

Es crucial entender la diferencia entre super y this. this siempre apunta al objeto actual (la instancia), mientras que super es una referencia al prototipo de la clase padre. Cuando llamas super.metodo(), estás ejecutando el método del padre, pero this dentro de ese método sigue apuntando al objeto actual. Esta distinción es sutil pero importante para entender cómo funciona la herencia.

super-vs-this.js
Loading code...

Este ejemplo demuestra la interacción entre super y this. Cuando Gato.describir() llama a super.describir(), ejecuta el método del padre Animal, pero this dentro de ese método sigue siendo el objeto Gato. Por eso super.describir() usa this.tipo = "Gato" (no "Animal genérico"). El método compararSonidos() muestra explícitamente cómo this.hacerSonido() llama a la versión de Gato, mientras super.hacerSonido() llama a la de Animal.

Resolución de métodos

Cuando usas this.metodo(), JavaScript busca el método empezando desde la clase actual y subiendo por la cadena de prototipos si no lo encuentra. Cuando usas super.metodo(), JavaScript salta directamente al prototipo del padre, ignorando cualquier versión del método en la clase actual. Esto te permite acceder específicamente a la implementación del padre incluso si la sobrescribiste.

this siempre es el objeto actual

Incluso cuando llamas super.metodo(), cualquier uso de this dentro de ese método del padre se refiere al objeto actual (la instancia), no a un hipotético "objeto padre". No existe un "objeto padre" separado; solo hay un objeto con una cadena de prototipos.

Errores Comunes

Hay varios errores comunes al usar super que es importante evitar. Estos errores generalmente resultan en ReferenceError o SyntaxError y pueden ser confusos para desarrolladores nuevos en la herencia de clases. Conocer estos errores te ayudará a escribir código correcto desde el principio.

  • <strong>Usar this antes de super()</strong>: Resulta en ReferenceError. super() debe ser lo primero.
  • <strong>Olvidar super() completamente</strong>: Si defines constructor en clase hija, super() es obligatorio.
  • <strong>Usar super sin extends</strong>: SyntaxError. super solo funciona con herencia.
  • <strong>Llamar super() dos veces</strong>: Error. Solo puedes llamar super() una vez por constructor.
  • <strong>super en arrow functions</strong>: Las arrow functions no tienen super, usa métodos normales.
errores-comunes.js
Loading code...

Este código muestra los errores más comunes con super y sus correcciones. Cada error está comentado con explicación del problema. El error más frecuente es usar this antes de super() en el constructor. También es común olvidar que super solo funciona en clases con extends. Las arrow functions como métodos de clase no tienen acceso a super, debes usar métodos normales.

Mensajes de error claros

Los errores relacionados con super generalmente tienen mensajes muy claros que indican exactamente qué está mal. Lee el mensaje de error cuidadosamente: te dirá si olvidaste super(), si lo usaste en el lugar equivocado, o si lo llamaste en un contexto inválido.

Ejemplo Práctico

Este ejemplo práctico muestra un sistema de notificaciones que usa super extensivamente. Demuestra cómo combinar super() en constructores, super.metodo() en métodos, y cómo extender funcionalidad de manera incremental a través de una jerarquía de clases.

ejemplo-practico.js
Loading code...

Este sistema de notificaciones muestra super en acción en un caso realista. La clase base Notificacion maneja funcionalidad común. NotificacionUrgente extiende obtenerContenido() con super para agregar marcas de urgencia, y sobrescribe marcarComoLeida() agregando logging antes de llamar a super. NotificacionEmail también extiende obtenerContenido() para agregar metadatos de email. Cada clase reutiliza funcionalidad del padre mientras agrega su comportamiento específico.

Extensión incremental

Este patrón de extender funcionalidad con super permite construir jerarquías donde cada nivel agrega valor incremental. La clase base proporciona funcionalidad común, y cada subclase la especializa sin duplicar código.

Resumen: La palabra clave super

Conceptos principales:

  • super() llama al constructor del padre, obligatorio si defines constructor
  • super.metodo() llama a métodos del padre para extender funcionalidad
  • super funciona en getters, setters y métodos estáticos
  • super solo funciona en clases con extends, no en clases sin herencia
  • this siempre apunta al objeto actual, incluso dentro de métodos del padre
  • super() debe ser la primera línea del constructor antes de usar this

Mejores prácticas:

  • Llama super() antes de usar this en constructores de clases hijas
  • Usa super.metodo() para extender funcionalidad, no duplicar código
  • Prefiere super sobre duplicar lógica del padre en métodos
  • Usa super en setters para crear validaciones en capas
  • No uses super en arrow functions, usa métodos normales
  • Lee mensajes de error cuidadosamente, indican exactamente el problema