Dominando el polimorfismo en Java: Conceptos, ejemplos y mejores prácticas
Polimorfismo en Java
Explora el polimorfismo en Java a través de explicaciones claras y ejemplos de código prácticos, y comprende cómo mejora la flexibilidad y reutilización del código.
El polimorfismo —un pilar esencial de la programación orientada a objetos— significa que una sola entidad puede tomar múltiples formas.
Es decir, la misma entidad (método, operador u objeto) puede realizar diferentes operaciones dependiendo del contexto.
Ejemplo: Polimorfismo en Java
class Poligono { // método para renderizar una forma public void renderizar() { System.out.println("Renderizando Polígono..."); } } class Cuadrado extends Poligono { // renderiza Cuadrado public void renderizar() { System.out.println("Renderizando Cuadrado..."); } } class Circulo extends Poligono { // renderiza círculo public void renderizar() { System.out.println("Renderizando Círculo..."); } } class Main { public static void main(String[] args) { // crear un objeto de Cuadrado Cuadrado c1 = new Cuadrado(); c1.renderizar(); // crear un objeto de Circulo Circulo c2 = new Circulo(); c2.renderizar(); } }
Salida
Renderizando Cuadrado... Renderizando Círculo...
En el ejemplo anterior, creamos una superclase: Poligono y dos subclases: Cuadrado y Circulo. El método renderizar() es heredado por ambas subclases, pero cada una lo sobrescribe para proporcionar lógica de renderizado específica de la forma.
La conclusión clave es que renderizar() se comporta diferente dependiendo del tipo de objeto real, que es la esencia del polimorfismo.
¿Por qué polimorfismo?
El polimorfismo permite a los desarrolladores escribir código limpio y consistente. En lugar de definir métodos separados como renderizarCuadrado() o renderizarCirculo(), un solo método renderizar() se adapta a cada forma, reduciendo redundancia y mejorando mantenibilidad.
Aunque métodos separados funcionarían, rápidamente llevan a duplicación de código y una API fragmentada. El polimorfismo unifica el comportamiento bajo un contrato común, asegurando que cualquier nueva forma pueda integrarse simplemente sobrescribiendo renderizar().
print() también demuestra polimorfismo —puede salida char, int, String y más sin requerir múltiples sobrecargas.Podemos lograr polimorfismo en Java usando las siguientes técnicas:
- Sobrescritura de métodos
- Sobrecarga de métodos
- Sobrecarga de operadores
Sobrescritura de métodos en Java
Cuando una subclase define un método con la misma firma que un método en su superclase, el método de la subclase sobrescribe el de la superclase. Esto permite que el mismo nombre de método realice diferentes operaciones basadas en el tipo de objeto en tiempo de ejecución.
Ejemplo 1: Polimorfismo usando sobrescritura de método
class Lenguaje { public void mostrarInfo() { System.out.println("Lenguaje Inglés Común"); } } class Java extends Lenguaje { @Override public void mostrarInfo() { System.out.println("Lenguaje de Programación Java"); } } class Main { public static void main(String[] args) { // crear un objeto de clase Java Java j1 = new Java(); j1.mostrarInfo(); // crear un objeto de clase Lenguaje Lenguaje l1 = new Lenguaje(); l1.mostrarInfo(); } }
Salida:
Lenguaje de Programación Java Lenguaje Inglés Común
Aquí, Lenguaje sirve como clase base y Java como subclase. El método mostrarInfo() está definido en ambas clases, pero cada implementación entrega información apropiada al contexto.
El método que se ejecuta se determina en tiempo de ejecución, por lo que este patrón se llama polimorfismo en tiempo de ejecución.

2. Sobrecarga de métodos en Java
La sobrecarga de métodos permite a una clase tener múltiples métodos con el mismo nombre pero diferentes listas de parámetros. El compilador resuelve qué método invocar basado en los argumentos suministrados.
void func() { ... } void func(int a) { ... } float func(double a) { ... } float func(int a, float b) { ... }
Esta técnica permite que la misma operación lógica acepte entradas variadas.
Ejemplo 3: Polimorfismo usando sobrecarga de método
class Patron { // método sin parámetro public void mostrar() { for (int i = 0; i < 10; i++) { System.out.print("*"); } } // método con un parámetro public void mostrar(char simbolo) { for (int i = 0; i < 10; i++) { System.out.print(simbolo); } } } class Main { public static void main(String[] args) { Patron d1 = new Patron(); // llamar método sin ningún argumento d1.mostrar(); System.out.println("\n"); // llamar método con un solo argumento d1.mostrar('#'); } }
Salida:
********** ##########
En este ejemplo, la clase Patron contiene dos métodos mostrar() sobrecargados. La versión sin parámetros imprime diez asteriscos, mientras que la que acepta un char imprime diez copias del símbolo suministrado.
Como el compilador selecciona el método en tiempo de compilación, esta forma de polimorfismo a menudo se refiere como polimorfismo en tiempo de compilación.
3. Sobrecarga de operadores en Java
Los operadores de Java pueden exhibir diferentes comportamientos basados en los tipos de operandos. Por ejemplo, el operador + realiza adición numérica cuando se usa con números y concatenación de cadenas cuando se usa con strings.
+puede sumar números o concatenar cadenas.- Operadores lógicos y bitwise como
&,|y!también se comportan diferente según los tipos de operandos.
A continuación hay fragmentos ilustrativos mostrando cómo + se adapta a sus operandos.
1. Con números:
int a = 5; int b = 6; // + con números int suma = a + b; // Salida = 11
2. Con cadenas:
String primero = "Java "; String segundo = "Programación"; // + con cadenas String nombre = primero + segundo; // Salida = Java Programación
Así, + está sobrecargado en Java para realizar tanto adición como concatenación.
Variables polimórficas
Una variable se considera polimórfica cuando puede referenciar objetos de diferentes tipos durante la ejecución del programa. En Java, las referencias de objeto habilitan este comportamiento, permitiendo que una referencia de un tipo base apunte a instancias de subclases.
Ejemplo: Variables polimórficas
class LenguajeProgramacion { public void mostrar() { System.out.println("Soy Lenguaje de Programación."); } } class Java extends LenguajeProgramacion { @Override public void mostrar() { System.out.println("Soy Lenguaje de Programación Orientado a Objetos."); } } class Main { public static void main(String[] args) { // declarar una variable de objeto LenguajeProgramacion lp; // crear objeto de LenguajeProgramacion lp = new LenguajeProgramacion(); lp.mostrar(); // crear objeto de clase Java lp = new Java(); lp.mostrar(); } }
Salida:
Soy Lenguaje de Programación. Soy Lenguaje de Programación Orientado a Objetos.
En esta ilustración, la referencia lp se declara con el tipo base LenguajeProgramacion pero se asignan objetos tanto de la clase base como de su subclase. Esto demuestra upcasting y polimorfismo en tiempo de ejecución.
Java
- Dominar Operadores en Java: Tipos, Sintaxis y Ejemplos Prácticos
- Dominando interfaces en Java: Conceptos, implementación y mejores prácticas
- Dominando Try‑with‑Resources en Java: Gestión automática de recursos explicada
- Anotaciones en Java explicadas: Tipos, ubicación y ejemplos prácticos
- Tipos de anotaciones en Java: Guía completa de predefinidas, personalizadas y meta‑anotaciones
- Método Java String length(): Cómo obtener el tamaño de un String (Ejemplo)
- Dominando Java String.indexOf(): Localizar subcadenas y ejemplos prácticos
- Entendiendo Java String.charAt(): Sintaxis, tipo de retorno, excepciones y ejemplo práctico
- Dominando Java String.endsWith(): Cómo comprobar sufijos de cadena con ejemplos
- Dominando el reemplazo de Strings en Java: replace(), replaceAll() y replaceFirst() explicados
- Sobrescritura de Métodos en Java: Personalizando el Comportamiento de la Superclase