martes, 21 de mayo de 2013

Herencia en Java

En esta ocasión vamos a profundizar un poco (desde el enfoque de programación, no teórico) en uno de los principales conceptos de programación orientada a objetos en java...............el concepto de Herencia, vamos a realizar un ejemplo practico para verificar su funcionamiento y aplicación en el desarrollo de software. 

Como se mencionó en la entrada anterior, básicamente mediante este concepto podemos obtener las características de una clase padre o de una jerarquía mayor dependiendo de nuestro árbol de herencia, en java definimos esta jerarquía mediante la palabra extends seguido del nombre de la clase a la que vamos a heredar, también se debe tener claro que solo se puede heredar de una sola clase pues el lenguaje no permite la Herencia múltiple (En Java por defecto todas las clases heredan de la clase Object, es decir, esta es la clase Padre de todas las clases en Java).

Antes de continuar, les comparto este video donde podràn complementar el concepto mediante otro ejemplo practico diferente al de esta entrada...


Requisitos.

Lo único que necesitamos para hacer el ejemplo practico es un entorno de desarrollo, conocer los conceptos de POO (vistos en la entrada anterior) y ganas de continuar :P para este caso usaremos el IDE Eclipse...........Empecemos.


El Ejemplo. 

Conociendo el concepto de clases y objetos vamos a asumir que necesitamos construir una aplicación sobre los diferentes tipos de vehículos existentes, pero para esto necesitamos clasificarlos, en este caso trabajaremos con vehículos acuáticos y aéreos.

Teniendo como punto de partida la información anterior podemos empezar a definir nuestras clases, vamos a trabajar con vehículos acuáticos y vehículos aéreos, entonces......... cual es el factor común de estos 2 tipos?..............................................

El factor común es que sin importar si es un avión o un barco, estamos hablando de vehículos, y ambos pueden compartir características comunes por esta razón la Clase principal de nuestro sistema sera la clase Vehiculo.

Partiendo de lo anterior podemos profundizar aun mas en nuestro árbol de herencia, sabemos que un barco o un avión son vehículos, pero será que esta información es suficiente???.......... sería correcto decir que ¿un barco es igual a un avión porque ambos son vehículos?..........definitivamente NO, ya que si bien descienden del mismo concepto de vehículo ambos tienen características propias que los diferencian, aquí es donde tenemos que pensar de forma general para poder definir un correcto árbol de herencia, por eso podemos decir que un barco además de descender de un vehículo, también desciende del tipo de vehículos Acuáticos los cuales tienen un conjunto de características comunes para cualquier vehículo acuático (sin olvidar que cada vehículo acuático puede tener sus características propias) y de la misma forma un avión desciende del tipo de vehículos Aéreos (con la misma lógica del anterior)............tenemos así nuestras clases Acuatico y Aereo que a su vez descienden de la clase Vehiculo, y son padres de cualquier vehículo en su jerarquía.

Al final tenemos definida nuestra estructura de clases (para este ejemplo no entraremos en detalles sobre las características a profundidad de cada clase, pero si alguna básica para resaltar el concepto) así:


Como vemos, la Clase Padre es Vehiculo, la cual tiene como hijas a las clases Acuatico y Aereo, estas a su vez son clases Padre de Barco, Velero, Avion y Helicoptero que a la vez son nietas de Vehiculo...Simple o ¿no?

Con esto ya tenemos una jerarquía de herencia definida, esto quiere decir que por ejemplo la clase Avion puede usar el método volar() de la clase Aereo, así como también usar el método transportar() de la clase Vehiculo, pues se encuentra en el mismo árbol de herencia, sin embargo no puede usar el método navegar() de la clase Acuatico, ya que no es de tipo Acuatico.

Teniendo nuestro diagrama definido, vamos a aplicar el concepto en Java.

Vehiculo.
Clase Padre.
/**
 * @author HENAO
 *
 */
public class Vehiculo {
 
 public int modeloVehiculo;
 
 public String nombreVehiculo="";
 
 public String transportar(){
  return "Metodo transportar de clase Vehiculo";
 }
}


Acuatico.
SubClase extiende de Vehiculo.
public class Acuatico extends Vehiculo{
 
 public String nombreAcuatico="";
 
 public String navegar(){
  return "Método navegar de clase Acuatico";
 }

}

Aereo.
SubClase extiende de Vehiculo.
public class Aereo extends Vehiculo {
 
 public String nombreAereo="";
 
 public String volar(){
  return "Método volar desde clase Aereo";
 }
}

Barco.
SubClase extiende de Acuatico.
public class Barco extends Acuatico {
 
 public String prenderMotor(){
   return "Método prenderMotor en clase Barco";
 }
}

Velero.
SubClase extiende de Acuatico.
public class Velero extends Barco{
 
 public String izarVelas(){
  return "Método izarVelas en clase Velero";
 }
}

Clase Avion. 
SubClase extiende de Aereo.
public class Avion extends Aereo{
 
 public String bajarTrenDeAterrizaje(){
  return "Método bajarTrenDeAterrizaje en clase Avion";
 }
}

Clase Helicoptero.
SubClase extiende de Aereo.
public class Helicoptero extends Aereo{
 
 public String encenderHelices(){
  return "Método encenderHelices en clase Helicoptero";
 }
}

Como vemos seguido del nombre de la clase se tiene la palabra extends la cual indica que se extiende o hereda de la clase definida, así mismo todas las clases tienen al menos un método que representa la característica propia de la clase, para las clases hijas ese método define el proceso que solo ellas pueden realizar, para las clases padre, ese método define el proceso que es común o general para las clases hijas.

Ahora veremos como funciona la herencia en nuestra aplicación.

Creamos una clase Principal donde se realizarán las operaciones, podemos crear instancias de las clases y verificar el nivel de acceso que tenemos a las características tanto de nuestra clase como de nuestra Jerarquía de Herencia, así.


En la imagen vemos que tenemos una instancia de la clase Vehículo, esto lo podemos traducir como la creación del objeto miVehiculo de tipo Vehiculo, no olvidemos que esta clase es la clase padre, por eso al verificar los métodos disponibles (En Eclipse después del punto hacemos Ctrl+espacio) vemos que nos aparecen las características propias de la clase, asi como otros métodos de la clase Object (Recordemos que en java todas las clases heredan de Object) que también podemos usar.


Al crear otro objeto de la clase Acuatico y realizar el mismo proceso anterior, vemos que ahora tenemos no solo los métodos propios de la clase sino también los métodos y atributos de la clase Vehiculo.

Ahora miremos un objeto de las clases Hijas.


Al crear un objeto de la clase Barco vemos que ahora no solo tenemos las características de Barco sino también podemos hacer uso de las características de Acuatico y de Vehiculo.

Este mismo principio aplica para la otra parte de nuestra jerarquía (Vehículos Aéreos) donde como mencionamos anteriormente solo podemos acceder a los métodos y atributos disponibles para ese árbol de herencia.

Veamos todo nuestro código...
public class Principal {

 /**
  * @param args
  */
 public static void main(String[] args) {
  
 System.out.println("*********************************************************************");
 System.out.println("*                        << CoDejaVu >>                             *");
 System.out.println("*                                                                   *");
 System.out.println("*********************************************************************");
 System.out.println();
 System.out.println("-------------------<< Clase Padre Vehiculo >>-----------------------");
 Vehiculo miVehiculo = new Vehiculo();
 miVehiculo.nombreVehiculo="El Gran Transportador";
 System.out.println("usando miVehiculo, nombreVehiculo : "+miVehiculo.nombreVehiculo);
 System.out.println("usando miVehiculo llama a: "+miVehiculo.transportar());
 System.out.println("--------------------------------------------------------------------");
 System.out.println();
 
 System.out.println("----------<< SubClase hija Acuatico Extiende de Vehiculo >>---------");
 Acuatico miAcuatico= new Acuatico();
 miAcuatico.nombreVehiculo="El Navegante";
 System.out.println("usando miAcuatico, nombreVehiculo : "+miAcuatico.nombreVehiculo);
 System.out.println("usando miAcuatico llama a : "+miAcuatico.transportar());
 System.out.println("usando miAcuatico llama a : "+miAcuatico.navegar());
 System.out.println("---------------------------------------------------------------------");
 System.out.println();
 
 System.out.println("-----<< SubClases hijas extienden de la Subclase Padre Acuatico>-----");
 Barco miBarco=new Barco();
 miBarco.nombreVehiculo="Titanic";
 System.out.println("usando miBarco, nombreVehiculo : "+miBarco.nombreVehiculo);
 System.out.println("usando miBarco llama a : "+miBarco.transportar());
 System.out.println("usando miBarco llama a : "+miBarco.navegar());
 System.out.println("usando miBarco llama a : "+miBarco.prenderMotor());
 System.out.println();
 
 Velero miVelero=new Velero();
 miVelero.nombreVehiculo="Tormenta";
 System.out.println("usando miVelero, nombreVehiculo : "+miVelero.nombreVehiculo);
 System.out.println("usando miVelero llama a : "+miVelero.transportar());
 System.out.println("usando miVelero llama a : "+miVelero.navegar());
 System.out.println("usando miVelero llama a : "+miVelero.izarVelas());
 System.out.println("---------------------------------------------------------------------");
 
 System.out.println("----------<< SubClase hija Aereo Extiende de Vehiculo >>---------");
 Aereo miAereo= new Aereo();
 miAereo.nombreVehiculo="El Volador";
 System.out.println("usando miAereo, nombreVehiculo : "+miAereo.nombreVehiculo);
 System.out.println("usando miAereo llama a : "+miAereo.transportar());
 System.out.println("usando miAereo llama a : "+miAereo.volar());
 System.out.println("---------------------------------------------------------------------");
 System.out.println();
 
 System.out.println("-----<< SubClases hijas extienden de la Subclase Padre Aereo >-----");
 Avion miAvion=new Avion();
 miAvion.nombreVehiculo="El Condor";
 System.out.println("usando miAvion, nombreVehiculo : "+miAvion.nombreVehiculo);
 System.out.println("usando miAvion llama a : "+miAvion.transportar());
 System.out.println("usando miAvion llama a : "+miAvion.volar());
 System.out.println("usando miAvion llama a : "+miAvion.bajarTrenDeAterrizaje());
 System.out.println();
 
 Helicoptero miHelicoptero=new Helicoptero();
 miHelicoptero.nombreVehiculo="El lobo del Aire";
 System.out.println("usando miHelicoptero, nombreVehiculo : "+miHelicoptero.nombreVehiculo);
 System.out.println("usando miHelicoptero llama a : "+miHelicoptero.transportar());
 System.out.println("usando miHelicoptero llama a : "+miHelicoptero.volar());
 System.out.println("usando miHelicoptero llama a : "+miHelicoptero.encenderHelices());
 System.out.println("---------------------------------------------------------------------");
 System.out.println();
 
 System.out.println("--<< Propiedad de la clase Vehiculo usada por todas las clases Hijas >--");
 System.out.println("nombre Vehiculo :"+miVehiculo.nombreVehiculo);
 System.out.println("nombre Acuatico :"+miAcuatico.nombreVehiculo);
 System.out.println("nombre Aereo :"+miAereo.nombreVehiculo);
 System.out.println("nombre Barco :"+miBarco.nombreVehiculo);
 System.out.println("nombre Velero :"+miVelero.nombreVehiculo);
 System.out.println("nombre Avion :"+miAvion.nombreVehiculo);
 System.out.println("nombre Helicoptero :"+miHelicoptero.nombreVehiculo);
 System.out.println("---------------------------------------------------------------------");
 
 }
}

Con este ejemplo hacemos el llamado a los métodos tanto propios como heredados de las clases padres, obteniendo el siguiente resultado.


Como vemos podemos acceder a los diferentes métodos desde otras clases, y si nos fijamos bien podemos identificar que siempre usamos la misma propiedad nombreVehiculo de la clase Vehiculo, lo hicimos usando objetos diferentes por tal razón el valor de la propiedad depende del asignado por cada objeto, convirtiéndose en un atributo del objeto y no de la clase como tal.


Conclusión

Podemos ver que la herencia va ligada a muchos otros conceptos, vimos el concepto de clase, el concepto de objetos entre otros, en este caso también es importante conocer el concepto de encapsulación ya que como compartimos características entre clases tenemos que estar seguros que la clase que accede puede usarlas, aunque mas adelante trataremos este tema a profundidad.........espero que esta entrada sea útil y fácil de entender...... 



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 ;)

8 comentarios:

  1. Hola, primero buen trabajo por tus explicaciones y por tu blog que es muy bueno.
    Ahora una pregunta sobre herencia (que espero que me puedas contestar). He visto muchas veces en herencia que cuando se hereda, al instanciar el objeto se coge primero la clase más alta posible por ejemplo al instanciar un objeto de barco (en tu ejemplo) sería así:

    Vehiculo v1 = new Barco();

    Y es algo que he preguntado mucho pero no me ha quedado muy claro, si es mejor instanciar con la clase padre de todo o da igual con la misma clase:

    Barco b1 = new Barco();

    Porque otras veces me han dicho que para hacer un ArrayList() es mejor instanciarlo de esta manera:

    List lista = new ArrayList();

    Ya que ArrayList hereda de List.

    Me gustaría saber que es mejor o peor para instanciar algo, ya que habría que utilizar instanceof posteriormente para saber de que tipo de objeto es.

    Espero que hayas entendido mi duda y puedas contestarla (cuando puedas). Un Saludo.

    ResponderEliminar
    Respuestas
    1. Hola, te cuento, la forma de como lo instancies, depende básicamente de lo que necesites hacer... si intancias con la clase Vehiculo quiere decir que necesitas heredar algo que esté en vehículo y por esa razón utilizas vehículo como la superClase para de esa forma tener el objeto v1 con características no solo del barco sino también de un vehículo.... por ende si instancias solo como barco pues quiere decir que tendrás un barco solo con las caracteristicas mínimas que necesites y que barco te provee.

      Basados en lo anterior pasa lo mismo con List y ArrayList... existen métodos propios de List que ArrayList no tiene, pero todo depende de las características que necesites utilizar......

      regresando con el ejemplo del Vehiculo y el Barco, a esa manera de instanciar se le conoce como polimorfismo, por eso tu puedes tener un avión y un barco que compartan la misma funcionalidad que exista en la clase Vehiculo (o si es una interface también), por ejemplo arrancar() es una acción que ambos realizan, entonces la puedes heredar, sea llamando al método o implementandolo en cada clase......en este ultimo caso puede que pienses que no tendría sentido, pero cuando son aplicaciones grandes esa pequeña acción podría jugar un papel importante a nivel de rendimiento o tiempo de ejecución..... un saludo y gracias por comentar ;) y en el indice de contenido hay algo sobre polimorfismo que te puede aclarar mucho mas ;)
      http://codejavu.blogspot.com/p/blog-page_12.html

      Eliminar
  2. Hola, entre a tu blog por casualidad, buscando entender un poco mas de herencia, ya que soy un viejo programador o programador viejo (en mi caso es lo mismo jajajajajaja). Mi duda es por que todas las variables las dejaste en public y no armaste sus respectivos set y get. Supongo que solo por una cuestion de hacerlo mas basico... Gracias

    ResponderEliminar
  3. no le entiendo nadita algien que pueda dar clases en lina dispuesto a pagar $500

    ResponderEliminar
    Respuestas
    1. https://www.youtube.com/watch?v=coK4jM5wvko&list=PLU8oAlHdN5BktAXdEVCLUYzvDyqRQJ2lk

      Eliminar
  4. public class Velero extends Barco?????

    ResponderEliminar
    Respuestas
    1. Hola, buscando la definición en google aparece esto: "[embarcación] Que es muy ligero." osea que a modo de ejemplo si aplicaria, cual seria la inquietud?

      Eliminar
  5. Muchas gracias por este material. Saludos desde Bogotá.

    ResponderEliminar

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