Polimorfismo en Java: Guía completa con ejemplos prácticos
¿Qué es el polimorfismo en Java?
El polimorfismo es un concepto central en la Programación Orientada a Objetos (POO) de Java. Surge cuando las clases están vinculadas por herencia, permitiendo que una única interfaz represente diferentes formas subyacentes. El resultado es que una llamada a método puede invocar diferentes implementaciones dependiendo del tipo de objeto real en tiempo de ejecución.
Piensa en un smartphone que puede comunicarse por llamada de voz, texto, imagen o email. El objetivo —comunicación— es el mismo, pero cada modo se comporta de forma distinta. Eso es polimorfismo en términos cotidianos.
Qué aprenderás
- Definición de polimorfismo en Java
- Ejemplos prácticos de POO
- Sobrescritura de métodos
- Sobrecarga vs. sobrescritura
- Polimorfismo dinámico (en tiempo de ejecución)
- Polimorfismo estático vs. dinámico
- La palabra clave
super
Polimorfismo en Java POO: Un ejemplo
Considera una clase base Cuenta que ofrece depositar() y retirar(). Dos subclases, CuentaAhorro y CuentaCorriente, heredan estos métodos sin cambios porque las operaciones son idénticas.

Adaptándose a requisitos cambiantes
Cuando se requiere una nueva característica —como una facilidad de descubierto—, una subclase CuentaPrivilegiada puede sobrescribir retirar() para proporcionar la nueva lógica sin tocar las subclases existentes. Esto demuestra la ventaja de mantenibilidad del polimorfismo.

Sobrescritura de métodos en Java
La sobrescritura ocurre cuando una subclase proporciona su propia implementación de un método ya definido en su superclase. La firma del método (nombre, parámetros, tipo de retorno) debe coincidir exactamente.
Reglas clave
- El método sobrescrito puede tener visibilidad más amplia (ej.
protectedapublic) pero nunca más restrictiva. - Los tipos de retorno deben ser los mismos o covariantes.
Ejemplo:
class Doctor {
public void tratarPaciente() {
// lógica común de tratamiento
}
}
class Cirujano extends Doctor {
@Override
public void tratarPaciente() {
// tratamiento quirúrgico especializado
}
}
public class Ejecutar {
public static void main(String[] args) {
Doctor doctor = new Doctor();
doctor.tratarPaciente(); // ejecuta Doctor.tratarPaciente()
Cirujano cirujano = new Cirujano();
cirujano.tratarPaciente(); // ejecuta Cirujano.tratarPaciente()
}
}
Sobrecarga vs. Sobrescritura
| Sobrecarga de métodos | Sobrescritura de métodos |
|---|---|
| Misma clase, mismo nombre, diferente lista de parámetros. | Método de superclase redefinido en subclase con firma idéntica. |
Ejemplo:void suma(int a, int b); |
Ejemplo:class X { int suma() { ... } }
class Y extends X {
@Override int suma() { ... }
} |
Polimorfismo dinámico (en tiempo de ejecución)
Cuando una referencia de superclase apunta a un objeto de subclase, la JVM resuelve la llamada al método en tiempo de ejecución. Esto es polimorfismo verdadero en acción.
Doctor doc = new Cirujano(); doc.tratarPaciente(); // Ejecuta Cirujano.tratarPaciente()
El método real invocado depende del tipo de objeto en tiempo de ejecución, no del tipo de referencia.
Polimorfismo estático vs. dinámico
El polimorfismo estático (sobrecarga) se resuelve en tiempo de compilación, mientras que el polimorfismo dinámico (sobrescritura) se resuelve en tiempo de ejecución.
| Polimorfismo estático | Polimorfismo dinámico |
|---|---|
| Sobrecarga de métodos; enlace en tiempo de compilación. | Sobrescritura de métodos; enlace en tiempo de ejecución. |
Ejemplo:void suma(int a, int b); |
Ejemplo:Doctor d = new Cirujano(); |
Uso de la palabra clave super
Cuando una subclase necesita extender un método de la superclase, super llama a la implementación del padre antes de añadir su propia lógica.
class Cirujano extends Doctor {
@Override
public void tratarPaciente() {
super.tratarPaciente(); // lógica base
// lógica específica del cirujano
}
}
De forma similar, super puede acceder a campos protected o public de la superclase.
Ejemplo práctico: Herencia, Polimorfismo y Super
Copia el código siguiente en tu IDE y observa la salida.
public class Test {
public static void main(String[] args) {
X x = new X();
Y y = new Y();
y.m2(); // Descomenta para ver efectos de herencia
// x.m1();
// y.m1();
// x = y; // referencia padre a objeto hijo
// x.m1();
// y.a = 10; // error: a es private
}
}
class X {
private int a;
int b;
public void m1() {
System.out.println("Este es el método m1 de la clase X");
}
}
class Y extends X {
int c;
@Override
public void m1() {
System.out.println("Este es el método m1 de la clase Y");
}
public void m2() {
super.m1();
System.out.println("Este es el método m2 de la clase Y");
}
}
Conclusiones clave
- El polimorfismo permite que los objetos tomen múltiples formas a través de la herencia.
- La sobrescritura de métodos cambia el comportamiento en subclases manteniendo la misma firma.
- El polimorfismo dinámico resuelve las llamadas a métodos en tiempo de ejecución, permitiendo código flexible.
- El polimorfismo estático (sobrecarga) es en tiempo de compilación, mientras que el dinámico es en tiempo de ejecución.
- La palabra clave
superpermite a las subclases invocar métodos del padre o acceder a miembros protegidos.
Java
- Clases Abstractas en C#: Tutorial Práctico con Ejemplos de Código
- Entendiendo Interfaces en C#: Definición, Ejemplo y Uso Práctico
- Dominando el polimorfismo en Java: Conceptos, ejemplos y mejores prácticas
- Conceptos de POO en Java: Fundamentos, ejemplos y ventajas
- Método Java String length(): Cómo obtener el tamaño de un String (Ejemplo)
- Entendiendo Java String.charAt(): Sintaxis, tipo de retorno, excepciones y ejemplo práctico
- Método Java String.contains(): Cómo comprobar subcadenas – Ejemplos prácticos
- Dominando Java String.endsWith(): Cómo comprobar sufijos de cadena con ejemplos
- Java Static explicado: Variables, métodos y bloques – Ejemplos prácticos
- Interfaz vs Clase Abstracta en Java: Cómo elegir la abstracción correcta
- Lectura de archivos en Java con BufferedReader – Guía práctica con ejemplos