sábado, 1 de junio de 2013

Ejemplo de Polimorfismo En Java

En esta entrada vamos a trabajar un ejemplo rápido y simple aplicando el concepto de Polimorfismo, en el post anterior vimos algunas consideraciones y reglas  importantes cuando trabajamos con objetos Polimorficos, si hay dudas sobre como aplicarse, se recomienda dar una mirada al post anterior.....

Sin mas rodeos, a lo que vinimos.....


Para este ejemplo vamos a trabajar usando una Interface, una clase Abstracta y 2 clases Concretas como vemos en el siguiente diagrama:




Podemos ver que se tiene un árbol de herencia definido, donde la clase Abstracta Animal implementa la interface IAnimal y al mismo tiempo es clase Padre de Gato y Perro, los cuales implementaran no solo los métodos abstractos de Animal sino también el método comunicarse() de la interface IAnimal.......en entradas anteriores vimos que una de las reglas al trabajar con clases abstractas o interfaces es que todas las clases concretas que desciendan de ellas, están obligadas a implementar sus métodos......... en este caso veremos como la clase Animal al ser abstracta no esta obligada a hacerlo, pero sus hijas si....

Veamos como se codifica el diagrama anterior en Java:

Interface IAnimal.
public interface IAnimal {
 
  int valor=5;

  /**
   * Método Comunicarse, sera implementado por las clases concretas
   * que hereden de la clase Animal
   */
   public void comunicarse();

}
La Interface IAnimal posee el método comunicarse() el cual es completamente abstracto, evidenciamos que no es necesario indicarlo mediante la palabra abstract...........De la misma forma tenemos el atributo valor el cual (al ser declarado en la interface) se comporta como una Constante, así que nunca va a cambiar (en la entrada sobre Interfaces indicamos el porqué de estas propiedades)....

Clase Abstracta Animal.
public abstract class Animal implements IAnimal {

 private String nombre;
 
 /**
  * Constructor de la clase Animal
  * @param nombre
  */
 public Animal (String nombre){
  this.nombre=nombre;
  System.out.println("Constructor Animal, " +
    "nombre del animal : "+this.nombre);
 }
 
 /**
  * Retorna el valor de nombre
  * @return
  */
 public String getNombre(){
  return nombre;
 }

 
 /**
  * Metodo Abstracto tipoAnimal, la implementación depende
  * de las clases concretas que extiendan la clase Animal
  */
 public abstract void tipoAnimal();
 
}


Como vemos tenemos la clase Abstracta que implementa la Interface IAnimal pero como mencionamos al principio, esta clase no esta obligada a implementar el método comunicarse() ya que también es clase abstracta.

Tenemos el método tipoAnimal() el cual si debe ser declarado como abstracto, evidenciamos también el atributo nombre el cual lo declaramos como private y solo accederemos a el en nuestro árbol de herencia, con el aplicamos un poquito el concepto de Encapsulación (pero no de la forma ideal, podemos ver una pequeña definición en la entrada sobre conceptos Básicos).

Clase Gato.
public class Gato extends Animal{

   /**
    * Constructor explicito clase Gato
    * @param nombre
    */
    public Gato(String nombre) {
  super(nombre);//envia el parametro a el constructor de la clase padre
 System.out.println("Constructor Gato, nombre : "+nombre);
    }

    public void tipoAnimal() {
 System.out.println("Tipo Animal : Es un Gato");
    }

    public void comunicarse(){
  System.out.println("Metodo comunicarse : El gato maulla... Miau Miau");
    }
}

Clase Perro.
public class Perro extends Animal{
 
  /**
   * @param nombre
   */
   public Perro(String nombre) {
   super(nombre);
   System.out.println("Constructor perro, nombre : "+nombre);
 }

 public void tipoAnimal() {
  System.out.println("Tipo Animal : Es un Perro");
 }
 
 public void comunicarse(){
  System.out.println("Metodo comunicarse : El perro Ladra... Guau Guau");
 } 
}

Como vemos las Clases Gato y Perro heredan de la clase abstracta Animal, por ende implementan el método tipoAnimal(), y como Animal implementa la interface IAnimal, entonces tanto Gato como Perro al ser clases concretas están obligadas a implementar el método comunicarse()....

En las clases también podemos ver que se utiliza la propiedad nombre que es enviada al constructor de Animal mediante el llamado a super(nombre).

Hasta aquí ya tenemos las clases del diagrama, ahora veamos como relacionarlas mediante una clase principal.

Clase Test.
public class Test {
 public static void main (String[] arg){

 /**Creamos anim, un objeto Perro de tipo Animal*/
 Animal anim= new Perro("goliath") ;
 anim.tipoAnimal();
 anim.comunicarse();
 System.out.println();
  
 /**Creamos perro, un objeto Perro de tipo Perro*/
 Perro perro=new Perro("hercules");
 perro.tipoAnimal();
 System.out.println();
  
 /**Creamos animalPolimorfico, un objeto perro de tipo Animal
  * asignamos una referencia ya existente*/
 Animal animalPolimorfico=perro;
 animalPolimorfico.tipoAnimal();
 System.out.println();
  
 /**reasignamos la referencia del objeto anim a el objeto perro
  * esto es valido ya que ambos son de tipo Perro*/
 perro=(Perro) anim;
 perro.tipoAnimal();
 System.out.println();
 
 /**Creamos gat, un objeto Gato de tipo Animal*/
 Animal gat=new Gato("pichi");
 gat.tipoAnimal();
 gat.comunicarse();
 System.out.println();
 
 /**Creamos cat, un objeto Gato de tipo IAnimal
  * Para esto aplicamos polimorfismo usando la Interface*/
 IAnimal cat = new Gato("pitufa");
 cat.comunicarse();
 
 System.out.println("\nConstante en la interfaz Animal : "+IAnimal.valor);
 } 
}

Esta clase permite la creación de Objetos Polimorficos donde vemos que podemos usar las superClases para crear objetos de sus subClases, de esa forma podemos decir que perro es un Animal o Gato es un Animal .... Al ejecutar obtenemos.


En este ejemplo creamos diferentes objetos uno a uno para verificar la aplicación del polimorfismo, pero esto también puede evidenciarse de otras maneras, por ejemplo podemos crear un arreglo de tipo Animal y en el almacenar objetos de su árbol de herencia.... veamos..

Agreguemos a la clase Test el siguiente código...
Animal animales[]= { new Perro("simon"),new Perro("paco"),new Gato("mimi")};
  for(Animal a : animales){
        a.tipoAnimal();
  }
  System.out.println();

Como mencioné hace un momento, tenemos un arreglo animales de tipo Animal donde en cada posición almacenamos diferentes objetos subClases de Animal, así que cuando recorremos el arreglo podemos acceder a las propiedades del objeto que corresponda, así como las de su superClase...


Si de pronto quisieramos agregar al arreglo animales un objeto de tipo Planta, esto nos arrojaría error, ya que planta no debería hacer parte de la Jerarquía definida para el arreglo con el que estamos trabajando, en otras palabras porque planta no es un Animal....


Conclusiones....

En los ejemplos pudimos aplicar las reglas de Polimorfismo vistas en la entrada anterior además también evidenciamos la aplicación de otros conceptos combinando algunos como la Herencia, Clases Concretas, Clases Abstractas, Interfaces.

Podemos resaltar el método comunicarse() que heredan las clases Perro y Gato, donde al ser un método abstracto nos permite dar la implementación que queramos dependiendo de quien lo use, entonces podemos ver que tanto perro como gato se comunican pero de forma distinta y esa diferencia se ve en nuestra implementación...

En general vimos la importancia de trabajar con un paradigma Orientado a Objetos, pues nos da facilidades tanto a nivel de optimización como a nivel de estructura y lógica de la aplicación, así como brindar claridad en los principales conceptos en torno a la POO...


Mas adelante nos adentraremos en el mundo de los Patrones de Diseño, donde se podrán evidenciar y aplicar los conceptos vistos nuevamente....




También te podría Interesar. 


¿Hay algo que quieras anexar o comentar sobre esta entrada?  no dudes en hacerlo.....y si te gustó, te invito a compartir y Suscribirte ingresando al botón "Participar en este sitio" para darte cuenta de mas entradas como esta ;)

18 comentarios:

  1. Enhorabuena, has sido premiado con el premio Liebster Award http://inconformistacivilizado.blogspot.com.es/2013/06/premio-liebster-award.html

    ResponderEliminar
    Respuestas
    1. Gracias por tan grato detalle, proximamente permitiré que el premio siga su rumbo!!!

      Eliminar
  2. nadie te agredece -.- seguro te tomó trabajo escribir todo esto, gracias.

    ResponderEliminar
  3. De seguro van a empezar a llegar los agradecimientos... este tipo de trabajo se ve bien recompensado en el tiempo ;)

    ResponderEliminar
    Respuestas
    1. Gracias Gustavo, me alegra ver este mensaje por aquí, y de todas formas con agradecimientos o sin ellos seguimos trabajando ;) un saludo (Y)

      Eliminar
  4. excelente trabajo muchas gracias por la ayuda!!!

    ResponderEliminar
    Respuestas
    1. Gracias a ti por el comentario, y me alegra bastante que te sirviera ;)

      Eliminar
  5. Muy buen trabajo, excelente explicación. También escribo un blog sobre Java, si puedes dale una revisada y te agradecería tus comentarios. Saludos.
    www.soft-mas.com

    ResponderEliminar
    Respuestas
    1. Hola Manuel, Gracias por comentar y ya he visto tu Blog, si no estoy mal lo conoci en las epocas del campus party aqui en colombia, vi un video que se publicó.... un saludo y claro que lo visitaré nuevamente.

      Eliminar
  6. Gracias, me permitiste entender mejor sobre polimorfisco y excelentes ejemplos :)

    Saludos AERT

    ResponderEliminar
  7. Buen post! Como sugerencia ...sería recomendable añadir la anotación @Override para la redefinición de métodos. Ej:
    public class Gato extends Animal{

    public Gato(String nombre) {...}

    @Override
    public void tipoAnimal() {...}

    @Override
    public void comunicarse(){...}
    }

    De esta forma:
    -El compilador chequeará que realmente estamos redefiniendo los métodos (evitando errores comunes, como escribir mal el nombre del método, distinto número de argumentos...).
    -Obtenemos un código más legible, porque con un simple golpe de vista podemos ver que se está redefiniendo un método.
    *Desde Java 1.6 también se puede utilizar con el mismo propósito cuando se implementan los métodos de las interfaces.

    Un saludo!

    ResponderEliminar
    Respuestas
    1. David gracias por tu aporte, tienes razón, mas adelante espero mencionar la anotación cuando vincule el tema sobre sobreCarga y SobreEscritura de metodos......Un Saludo ;)

      Eliminar
  8. Buen trabajo. Esperando con ganas los temas de sobreCarga y SobreEscritura.

    Un Salduo.

    ResponderEliminar
    Respuestas
    1. Hola, muchas gracias, ya estoy adelantando algunas entradas entonces dentro de poco las presentaré... gracias nuevamente por comentar ;)

      Eliminar

Eres libre de realizar cualquier comentario, desde que pueda ayudar con gusto lo atenderé, y si es un critica, bienvenida sea!!!