Herramientas de usuario

Herramientas del sitio


bloque3:polimorfismo

Herencia: Polimorfismo

El polimorfismo es otro de los pilares de la programación orientada a objetos, junto al encapsulamiento, la abstracción, y la herencia. Está completamente ligado al mecanismo de herencia.

Básicamente consiste en acceder a métodos de 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 aparentemente un mismo objeto que se comporta de formas distintas.

De una forma resumida se puede decir que consiste en realizar un casting entre objetos: una variable de una superclase puede almacenar referencias de objetos de sus subclases. Podemos usar una variable de una superclase para acceder desde ella a métodos sobrescritos en la subclase.

Para explicar esto vamos a crear 3 clases: Vehiculo (Superclase), Coche y Moto (Subclases)

public Class Vehiculo{
   private int numRuedas;
   private int potencia;
   private String 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;
   ...
 
   @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;
   ...
 
   @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(); //ejecuta el método de la clase Vehiculo
vehiculo2.mostrarEspecificaciones(); //ejecuta el método de la clase Moto
vehiculo3.mostrarEspecificaciones(); //ejecuta el método de la clase Coche
 
 
//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 de la clase Coche
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.

if(vehiculo.getClass() == Coche.class){
   System.out.println("Es un coche");
}

© 2020 Fernando Valdeón

bloque3/polimorfismo.txt · Última modificación: 03/04/2019 20:02 por Fernando Valdeón