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
@Overridepara redefinir métodos heredados. - Aprovecha las clases abstractas e interfaces para diseñar sistemas polimórficos más robustos.