Command Palette

Search for a command to run...

ES·EN

Nivel 1 · 20 min

Herencia y Polimorfismo

La herencia permite que una clase (subclase) herede atributos y comportamientos de otra (superclase). El polimorfismo permite que el mismo código trabaje con objetos de distintos tipos — el tipo dinámico en tiempo de ejecución determina qué método se ejecuta. Juntos son poderosos pero requieren disciplina para no crear jerarquías frágiles.

Herencia y sobreescritura

En Java, extends hereda implementación. Una subclase puede sobreescribir métodos (override) con @Override. El método sobreescrito debe tener la misma firma o covariance en el tipo de retorno. La palabra super permite llamar al método de la superclase. Regla clave: sobreescribir es para especializar comportamiento, no para reemplazarlo completamente. Si reemplazás todo el comportamiento del padre, la herencia no agrega valor.

Polimorfismo y dispatch

El polimorfismo de subtipos permite que una referencia de tipo Animal apunte a objetos Dog, Cat, Bird. Cuando llamás animal.sound(), el JVM ejecuta el método del tipo dinámico (Dog.sound()) no del tipo de referencia (Animal.sound()). Esto es late binding o dynamic dispatch. El polimorfismo hace que el código sea extensible — podés agregar nuevas subclases sin modificar el código que trabaja con la superclase.

Covarianza, contravarianza y LSP

Covarianza: un subtipo puede devolver un subtipo más específico que el padre (covariant return types en Java). Contravarianza: un subtipo puede aceptar un supertipo más general como parámetro. El Principio de Sustitución de Liskov (LSP) formaliza la regla: si S es subtipo de T, los objetos de T pueden ser reemplazados por objetos de S sin alterar el comportamiento. La prueba: si tu código que espera Animal falla cuando recibe Dog, violás LSP.

Puntos clave

  • La herencia modela ''es-un''. Si la relación no es genuinamente ''es-un'', usá composición.
  • Dynamic dispatch significa que el método que se ejecuta se determina en runtime por el tipo real del objeto, no por el tipo de la referencia.
  • LSP es el test para la herencia correcta: los subtipos no deben sorprender al código que usa el supertipo.

Code example

// Polimorfismo: mismo codigo, distintos comportamientos
List'<'Shape'>' shapes = List.of(new Circle(5), new Rectangle(3, 4));
double totalArea = shapes.stream()
  .mapToDouble(Shape::area) // dispatch dinamico
  .sum();
// Circle.area() y Rectangle.area() se llaman correctamente