¡Esta es una revisión vieja del documento!
Tabla de Contenidos
Herencia: Polimorfismo
El polimorfismo es otro de los pilares de la programación orientada a objetos, junto al encapsulamiento, la abstacción, y la herencia. Está completamente ligado al mecanismo de herencia.
Básicamente consiste en acceder a una subclase mediante un tipo de datos de su superclase.
Concepto de polimorfismo
Viene del término de biología en el que un organismo puede tener diferentes formas. En programación orientada a objetos podemos tener un aparentemente un objeto que se comporta de modo distinto.
Para explicar esto vamos a crear 3 clases: Vehiculo, Coche y Moto
public Class Vehiculo{ private int numRuedas; private int potencia; private String matricula; ... public Vehiculo(String matricula, int potencia, int numRuedas){ this.numRuedas = numRuedas; this.potencia = potencia; this.matricula = matricula; } public void mostrarEspecficaciones(){ System.out.println("Especificaciones del vehiculo:"); System.out.println("Cantidad de ruedas: " + numRuedas); System.out.println("CV de Potencia: " + potencia); System.out.println("Nº de Matricula: " + matricula); } }
A continuación creamos dos subclases: Coche y Moto
//Clase Coche public class Coche extends Vehiculo{ private int numPuertas; public Coche(String matricula, int potencia, int numRuedas, int numPuertas){ super(matricula, potencia, numRuedas); this.numPuertas = numPuertas; public int getNumPuertas(){ return numPuertas; } @Override public void mostrarEspecficaciones(){ super.mostrarEspecificaciones(); System.out.println("Nº de puertas del coche: " + numPuertas); System.out.println("El Vehiculo es un coche"); } } //Clase Moto public class Moto extends Vehiculo{ private String marca; public Moto(String matricula, int potencia, int numRuedas, String marca){ super(matricula, potencia, numRuedas); this.marca = marca; } public String getMarca(){ return marca; } @Override public void mostrarEspecficaciones(){ super.mostrarEspecificaciones(); System.out.println("Marca de la moto: " + marca); System.out.println("El Vehiculo es una moto"); } }
Uso de polimorfismo
Ahora que ya tengo las 3 clases creadas, vamos a ver en qué consiste:
//Creo un vehiculo con matricula, potencia y ruedas Vehiculo vehiculo1 = new Vehiculo("FWD-2343",102, 3); //Creo otro vehiculo de subtipo Moto Vehiculo vehiculo2 = new Moto("ASD-1234", 160, 2, Yamaha); //Creo otro vehiculo de subtipo Coche Vehiculo vehiculo3 = new Coche("FGH-5678", 200, 4, 5); //Ejecuto el mismo método para los 3 vehiculos //El mismo método actúa de forma distinta vehiculo1.mostrarEspecificaciones(); vehiculo1.mostrarEspecificaciones(); vehiculo1.mostrarEspecificaciones(); //Intento acceder a métodos de las subclases vehiculo2.getMarca(); vehiculo3.getNumPuertas() //No es posible ya que el tipo Vehiculo no tiene esos métodos
Se puede llamar al método mostrarEspecificaciones()
ya que es un método de la clase Vehículo. Cuando se ejecuta ese método primero se busca si existe en el objeto que tengo guardado en la variable, y sino existe buscaré en el de la superclase, y así sucesivamente, hasta la clase Object.
Sin embargo si desde una variable de la superclase Vehiculo
quiero acceder a algún método de alguna subclase (getNumPuertas() ó getMarca()), no se permite, ya que no están definidos en esa clase.
Tampoco se permite almacenar un objeto de la superclase en una variable de una subclase:
Coche coche = new Vehiculo("ERT-653", 90, 4); //Error de compilación
UpCasting
Como hemos visto, podemos referenciar objetos de una subclase mediante variable de un superclase.
Vehiculo vehiculo1; vehiculo1 = new Coche();
Esto se conoce como UpCasting, o conversión hacia arriba (desde una subclase a una superclase). Es un casting implícito y no es necesario indicar ninguna instrucción para realizar la conversión.
Cualquier objeto se puede castear implícitamente a una variable de tipo Object
, ya que es la superclase de cualquier otra clase.
Con el UpCasting ganamos generalización, pero perdemos información acerca de los subtipos que casteamos (Coche en este caso). Ya no podemos acceder a los métodos miembro de la clase Coche, porque no están definidos en la superclase Vehiculo.
DownCasting
Si se quiere recuperar la información de una subclase cuando tenemos una variable de la superclase, será necesario moverse hacia abajo en la jerarquía mediante una conversión de tipo.
Esta conversión a un tipo más específico (subclase) desde un tipo más general, se conoce como DownCasting o conversión hacia abajo, y se realiza mediante una operación de casting:
//UpCasting Vehiculo vehiculo1 = new Coche(); Vehiculo vehiculo2 = new Moto(); //No puedo llamar al método vehiculo1.getNumPuertas(); //DownCasting Coche miCoche = (Coche) vehiculo1(); Moto miMoto = (Moto) vehiculo2(); //Puedo volver a llamar a sus métodos miembro miCoche.getNumPuertas(); miMoto.getNumPuertas(); //También se permite ((Coche)vehiculo1).getNumPuertas(); ((Moto)vehiculo2).getMarca();
Operador instanceof
Como acabamos de ver, es posible que una variable de referencia de un tipo más general (Vehiculo) pueda contener la referencia de algún subtipo (subclase de Vehiculo) de objeto.
Esto nos facilita las cosas cuando trabajamos con distintas subclases, ya que podemos tratarlas como un elemento de la superclase:
ArrayList<Vehiculo> listaVehiculos = new ArrayList<Vehiculo>(); listaVehiculos.add(new Coche()); listaVehiculos.add(new Moto()); listaVehiculos.add(new Camion()); listaVehiculos.add(new Avion());
Pero como también hemos dicho, puede que perdamos información acerca de cada objeto almacenado.
El operador instanceof
nos indica el tipo de objeto que tenemos en una variable de la superclase:
for(Vehiculo vehiculo : listaVehiculos){ if(vehiculo instanceof Coche){ //Lo gestiono como coche Coche coche = (Coche)vehiculo; }else if(vehiculo instanceof Moto){ //Lo gestiono como moto Moto moto = (Moto)vehiculo; }else if(vehiculo instanceof Camion){ //Lo gestiono como camion Camion camion = (Camion)vehiculo; }else if(vehiculo instanceof Avion){ //Lo gestiono como avion Avion avion = (Avion)vehiculo; } }
También tenemos el método getClass()
heredado desde la clase Object
que nos aporta una funcionalidad parecida.
© 2025 Fernando Valdeón