El polimorfismo permite que una misma llamada a un método produzca resultados distintos según el tipo dinámico del objeto que la recibe. Aunque una variable tenga un tipo declarado (estático), el método que se ejecuta en tiempo de ejecución depende del tipo real (dinámico) del objeto.

Este comportamiento es clave en la herencia, ya que permite sustituir una superclase por una subclase sin modificar el código cliente, siempre que se respeten los contratos definidos por la superclase.

instanceof

El operador instanceof se usa para comprobar si un objeto es una instancia de una clase determinada o de alguna de sus subclases.

Devuelve true o false y se evalúa en tiempo de ejecución, por lo que depende del tipo dinámico del objeto.

Casting

Un casting permite convertir una referencia entre tipos compatibles dentro de una jerarquía de herencia.

  • Ascendente (upcasting): de subclase a superclase. Es automático y seguro.

  • Descendente (downcasting): de superclase a subclase. Es explícito y puede fallar si el tipo real no es compatible, por lo que suele usarse junto a instanceof.

Animal a = new Perro(); if (a instanceof Perro) { “ Perro p = (Perro) a; // downcasting seguro `}