Historia de la pregunta:
El polimorfismo es uno de los principios clave de la programación orientada a objetos (OOP), que ha sido soportado en Java desde su creación. Permite que un objeto se comporte de manera diferente dependiendo de su tipo real durante la ejecución del programa, incluso si se utiliza una referencia de tipo base.
Problema:
Sin polimorfismo, el código se vuelve inflexible, a menudo aparecen construcciones redundantes del tipo switch-case o if-else para trabajar con objetos de diferentes tipos. Esto complica el mantenimiento y la expansión del código. El polimorfismo resuelve el problema de la necesidad de escribir código repetido para diferentes tipos.
Solución:
El polimorfismo en Java se implementa a través de la herencia y las interfaces. Permite:
Ejemplo de código:
class Animal { void speak() { System.out.println("Animal habla"); } } class Dog extends Animal { @Override void speak() { System.out.println("El perro ladra"); } } class Cat extends Animal { @Override void speak() { System.out.println("El gato maulla"); } } public class PolyDemo { public static void main(String[] args) { Animal a1 = new Dog(); Animal a2 = new Cat(); a1.speak(); // El perro ladra a2.speak(); // El gato maulla } }
Características clave:
¿Cuál es la diferencia entre sobrecarga (overloading) y sobreescritura (overriding) de métodos en el polimorfismo?
La sobrecarga es la definición de varios métodos con el mismo nombre, pero con una firma diferente en una clase. La sobreescritura es la definición de un método en una subclase con la misma firma que en la clase padre.
class Example { void foo(int x) {} void foo(String y) {} // esto es sobrecarga } class Base { void foo() {} } class Child extends Base { @Override void foo() {} // esto es sobreescritura }
¿Puede haber polimorfismo sin herencia?
En el sentido clásico en Java, no: el polimorfismo requiere la existencia de una jerarquía de herencia o una interfaz implementada.
¿Se pueden invocar métodos de la subclase desde una referencia de la clase padre?
Solo se pueden invocar los métodos definidos en la clase padre o sobreescritos en la subclase. Los métodos que solo existen en la subclase no pueden ser llamados sin un casting de tipo.
Animal a = new Dog(); a.speak(); // se puede // a.fetch(); // error de compilación, incluso si Dog tiene el método fetch()
En el proyecto se implementaron las clases Dog, Cat, Cow, pero el código utilizado trabajaba directamente con los tipos, llamando a los métodos a través de casting explícitos e instanceof:
Ventajas:
Desventajas:
Herencia de Animal con un speak() virtual. Toda la interacción a través del tipo base Animal.
Ventajas:
Desventajas: