El polimorfismo es uno de los pilares fundamentales de la programación orientada a objetos. Permite que una referencia a una clase pueda comportarse de diferentes maneras dependiendo del objeto que se asocie. En este artículo, exploraremos cómo Java implementa polimorfismo a través de la herencia y la redefinición de métodos.
1. ¿Qué es el polimorfismo?
El término «polimorfismo» significa muchas formas. En Java, esto implica que:
- Una misma referencia de tipo padre puede apuntar a objetos de diferentes subclases.
- Los métodos de una subclase pueden sobrescribir el comportamiento de los métodos heredados.
2. Polimorfismo a través de herencia
Ejemplo básico:
public class Animal { public void hacerSonido() { System.out.println("El animal hace un sonido."); } } public class Perro extends Animal { @Override public void hacerSonido() { System.out.println("El perro ladra."); } } public class Gato extends Animal { @Override public void hacerSonido() { System.out.println("El gato maúlla."); } } public class Principal { public static void main(String[] args) { Animal miAnimal; miAnimal = new Perro(); miAnimal.hacerSonido(); // El perro ladra. miAnimal = new Gato(); miAnimal.hacerSonido(); // El gato maúlla. } }
Salida:
El perro ladra. El gato maúlla.
3. Redefinición de métodos (@Override
)
La redefinición (o sobrescritura) permite que una subclase modifique el comportamiento de un método heredado. Para sobrescribir correctamente un método, sigue estas reglas:
- Misma firma: El nombre, tipo de retorno y parámetros deben coincidir exactamente.
- Compatibilidad con modificadores: No puedes hacer el método más restrictivo en la subclase.
- Usa la anotación
@Override
: Ayuda a evitar errores y hace el código más legible.
Ejemplo de redefinición:
public class Vehiculo { public void arrancar() { System.out.println("El vehículo está arrancando."); } } public class Coche extends Vehiculo { @Override public void arrancar() { System.out.println("El coche está arrancando."); } }
4. Llamar al método original con super
Si necesitas acceder al método de la superclase desde la subclase, usa super
.
Ejemplo práctico:
public class Vehiculo { public void arrancar() { System.out.println("El vehículo está arrancando."); } } public class Moto extends Vehiculo { @Override public void arrancar() { super.arrancar(); System.out.println("La moto está lista para rodar."); } } public class Principal { public static void main(String[] args) { Moto miMoto = new Moto(); miMoto.arrancar(); } }
Salida:
El vehículo está arrancando. La moto está lista para rodar.
5. Polimorfismo y tipos genéricos
El polimorfismo también permite almacenar diferentes tipos de objetos en estructuras genéricas, como listas.
Ejemplo con listas:
import java.util.ArrayList; public class Principal { public static void main(String[] args) { ArrayList<Animal> animales = new ArrayList<>(); animales.add(new Perro()); animales.add(new Gato()); for (Animal animal : animales) { animal.hacerSonido(); } } }
Salida:
El perro ladra. El gato maúlla.
6. Polimorfismo y clases abstractas
Las clases abstractas y las interfaces son herramientas clave para implementar polimorfismo.
Ejemplo con una clase abstracta:
public abstract class Figura { public abstract double calcularArea(); } public class Circulo extends Figura { private double radio; public Circulo(double radio) { this.radio = radio; } @Override public double calcularArea() { return Math.PI * radio * radio; } } public class Rectangulo extends Figura { private double base, altura; public Rectangulo(double base, double altura) { this.base = base; this.altura = altura; } @Override public double calcularArea() { return base * altura; } } public class Principal { public static void main(String[] args) { Figura miFigura; miFigura = new Circulo(5); System.out.println("Área del círculo: " + miFigura.calcularArea()); miFigura = new Rectangulo(4, 6); System.out.println("Área del rectángulo: " + miFigura.calcularArea()); } }
Salida:
Área del círculo: 78.53981633974483 Área del rectángulo: 24.0
7. Ventajas del polimorfismo
- Flexibilidad:
Puedes escribir código que funcione con diferentes tipos de objetos. - Reutilización de código:
Reduce duplicación al usar métodos genéricos. - Mantenimiento:
Agregar nuevas subclases no requiere cambios en el código existente que usa polimorfismo.
8. Errores comunes con polimorfismo
Llamar métodos no definidos en la superclase:
Solo puedes usar métodos que existen en la superclase.
Animal miAnimal = new Perro(); miAnimal.ladrar(); // Error: "ladrar" no está definido en Animal
Olvidar usar @Override
:
Si no lo usas, Java no detectará errores en la firma del método redefinido.
Resumen
- El polimorfismo permite trabajar con objetos de diferentes subclases a través de una referencia común.
- Usa
@Override
para redefinir métodos heredados. - Aprovecha las clases abstractas e interfaces para diseñar sistemas polimórficos más robustos.