La herencia es una caracterstica de los lenguajes de programacin orientado a objetos lo cual
facilita en la reutilizacin del cdigo como se mencion en temas anteriores. La herencia consiste en hacer uso de los atributos o mtodos de una clase dentro de otra como si le perteneciera a este mismo. Esto se podra dar en un caso muy exclusivo para poder ahorrar proceso y cdigo a implementar. Por ejemplo podra ser para una serie de empleados que ocupen diferentes cargos pero tienen atributos en comn como el nombre, apellido, DNI, etc. Lo cual sera conveniente usar la herencia juntando los datos en comn en una misma clase y distribuir clases independientes para los dems datos de los empleados.
Veamos un ejemplo simple de la herencia, para este caso crearemos una clase la cual heredaremos donde se encuentre el apellido y otra clase donde asignemos el nombre de una X persona. Primero veamos la clase que se heredar:
package herencia; public class ClaseHeredada { String Apellido; public ClaseHeredada(String Dato){ this.Apellido=Dato;} }
Una vez que tengamos la clase que heredaremos creamos nuestra clase donde se encontrar el nombre de la persona X y le asignamos el siguiente cdigo:
package herencia; public class Herencia extends ClaseHeredada{ String Nombre; public Herencia(String Texto){ super(Texto); } public void setPersona(String NombrePer){ this.Nombre=NombrePer+this.Apellido; } public String getPersona(){ return Nombre; } }
Se extends para indicar que estamos heredando la clase ClaseHeredada donde se encuentra elapellido. El super es para indicar que estamos instanciando al constructor de la clase que estamos heredando y los mtodos setPersona y getPersona son con los cuales capturaremos y recuperemos el nombre de la persona.
Una vez realizado este proceso, pasamos a usar la clase instanciando en nuestro main de la siguiente forma:
Instanciamos la Clase Herencia pasndole a su constructor el apellido de la persona lo cual internamente lo pasar a la clase superior ClaseHeredada, luego le asignamos el nombre haciendo uso de su mtodo setPersona y lo imprimimos mediante getPersona. Realizado este cdigo debera imprimir el nombre de la persona concatenando el apellido del mismo.
Herencia en Java En esta ocasin vamos a profundizar un poco (desde el enfoque de programacin, no terico) en uno de los principales conceptos de programacin orientada a objetos en java...............el concepto de Herencia, vamos a realizar un ejemplo practico para verificar su funcionamiento y aplicacin en el desarrollo de software.
Como se mencion en la entrada anterior, bsicamente mediante este concepto podemos obtener las caractersticas de una clase padre o de una jerarqua mayor dependiendo de nuestro rbol de herencia, en java definimos esta jerarqua mediante la palabra extends seguido del nombre de la clase a la que vamos a heredar, tambin se debe tener claro que solo se puede heredar de una sola clase pues el lenguaje no permite la Herencia mltiple (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).
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 aplicacin sobre los diferentes tipos de vehculos existentes, pero para esto necesitamos clasificarlos, en este caso trabajaremos con vehculos acuticos y areos.
Teniendo como punto de partida la informacin anterior podemos empezar a definir nuestras clases, vamos a trabajar con vehculos acuticos y vehculos areos, entonces......... cual es el factor comn de estos 2 tipos?..............................................
El factor comn es que sin importar si es un avin o un barco, estamos hablando de vehculos, y ambos pueden compartir caractersticas comunes por esta razn 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 avin son vehculos, pero ser que esta informacin es suficiente???.......... sera correcto decir que un barco es igual a un avin porque ambos son vehculos?..........definitivamente NO, ya que si bien descienden del mismo concepto de vehculo ambos tienen caractersticas 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 adems de descender de un vehculo, tambin desciende del tipo de vehculos Acuticos los cuales tienen un conjunto de caractersticas comunes para cualquier vehculo acutico (sin olvidar que cada vehculo acutico puede tener sus caractersticas propias) y de la misma forma un avin desciende del tipo de vehculos Areos (con la misma lgica del anterior)............tenemos as nuestras clases Acuatico y Aereo que a su vez descienden de la clase Vehiculo, y son padres de cualquier vehculo en su jerarqua.
Al final tenemos definida nuestra estructura de clases (para este ejemplo no entraremos en detalles sobre las caractersticas a profundidad de cada clase, pero si alguna bsica para resaltar el concepto) as:
Como vemos, la Clase Padre es Vehiculo, la cual tiene como hijas a las clasesAcuatico y Aereo, estas a su vez son clases Padre de Barco, Velero, Avion yHelicoptero que a la vez son nietas de Vehiculo...Simple o no?
Con esto ya tenemos una jerarqua de herencia definida, esto quiere decir que por ejemplo la clase Avion puede usar el mtodo volar() de la clase Aereo, as como tambin usar el mtodo transportar() de la clase Vehiculo, pues se encuentra en el mismo rbol de herencia, sin embargo no puede usar el mtodo navegar() de la clase Acuatico, ya que no es de tipo Acuatico.
Teniendo nuestro diagrama definido, vamos a aplicar el concepto en Java.
public String transportar(){ return "Metodo transportar de clase Vehiculo"; 12 13 14 } }
Acuatico. SubClase extiende de Vehiculo. 1 2 3 4 5 6 7 8 9 public class Acuatico extends Vehiculo{
public String nombreAcuatico="";
public String navegar(){ return "Mtodo navegar de clase Acuatico"; }
}
Aereo. SubClase extiende de Vehiculo. 1 2 3 4 5 6 7 8 public class Aereo extends Vehiculo {
public String nombreAereo="";
public String volar(){ return "Mtodo volar desde clase Aereo"; } }
Barco. SubClase extiende de Acuatico. 1 2 3 4 5 6 public class Barco extends Acuatico {
public String prenderMotor(){ return "Mtodo prenderMotor en clase Barco"; } }
Velero. SubClase extiende de Acuatico. 1 2 3 4 5 6 public class Velero extends Barco{
public String izarVelas(){ return "Mtodo izarVelas en clase Velero"; } }
Clase Avion. SubClase extiende de Aereo. 1 2 3 4 5 6 public class Avion extends Aereo{
public String bajarTrenDeAterrizaje(){ return "Mtodo bajarTrenDeAterrizaje en clase Avion"; } }
Clase Helicoptero. SubClase extiende de Aereo. 1 2 3 4 5 6 public class Helicoptero extends Aereo{
public String encenderHelices(){ return "Mtodo 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 mtodo que representa la caracterstica propia de la clase, para las clases hijas ese mtodo define el proceso que solo ellas pueden realizar, para las clases padre, ese mtodo define el proceso que es comn o general para las clases hijas.
Ahora veremos como funciona la herencia en nuestra aplicacin.
Creamos una clase Principal donde se realizarn las operaciones, podemos crear instancias de las clases y verificar el nivel de acceso que tenemos a las caractersticas tanto de nuestra clase como de nuestra Jerarqua de Herencia, as.
En la imagen vemos que tenemos una instancia de la clase Vehculo, esto lo podemos traducir como la creacin del objeto miVehiculo de tipo Vehiculo, no olvidemos que esta clase es la clase padre, por eso al verificar los mtodos disponibles (En Eclipse despus del punto hacemos Ctrl+espacio) vemos que nos aparecen las caractersticas propias de la clase, asi como otros mtodos de la clase Object (Recordemos que en java todas las clases heredan de Object) que tambin podemos usar.
Al crear otro objeto de la clase Acuatico y realizar el mismo proceso anterior, vemos que ahora tenemos no solo los mtodos propios de la clase sino tambin los mtodos 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 caractersticas de Barco sino tambin podemos hacer uso de las caractersticas de Acuatico y de Vehiculo.
Este mismo principio aplica para la otra parte de nuestra jerarqua (Vehculos Areos) donde como mencionamos anteriormente solo podemos acceder a los mtodos y atributos disponibles para ese rbol de herencia.
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 mtodos tanto propios como heredados de las clases padres, obteniendo el siguiente resultado.
Como vemos podemos acceder a los diferentes mtodos 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 razn el valor de la propiedad depende del asignado por cada objeto, convirtindose en un atributo del objeto y no de la clase como tal.
Conclusin
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 tambin es importante conocer el concepto de encapsulacin ya que como compartimos caractersticas 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 fcil de entender......
Polimorfismo en Java Al escuchar la palabra polimorfismo lo primero que se nos viene a la mente es "Muchas Formas" y bueno, si, bsicamente esta es la idea general, pero y que mas gira en torno a esto???........
en esta entrada veremos algunos ejemplos y puntos a tener en cuenta sobre el polimorfismo en la programacin orientada a objetos y para eso aplicaremos otros conceptos trabajados con anterioridad..... y mas adelante desarrollaremos un ejemplo en Java donde pondremos a prueba lo aprendido en esta entrada......
Algunas Ideas.
Como se mencion en la entrada sobre Conceptos Bsicos, podemos definirlo como la capacidad que tienen los objetos de comportarse de mltiples formas, programando de manera general en vez de hacerlo de forma especifica... Alguna vez consultando, definan este concepto como la forma en la que podemos tratar una subClase como si fuera una Clase del tipo de su superClase, usando solo los mtodos o atributos disponibles para la Clase declarada..... es decir, si tenemos una clase "X" podemos decir que "X" es de tipo "Y" esto se cumple solo si existe una relacin de herencia entre ellas, ya sea si "X" hereda de "Y" (extends) o si "X" implementa a "Y" (implements)
Retomando (de manera reducida) el ejemplo de la entrada sobre conceptos bsicos en el punto sobre polimorfismo, se explica mejor lo anterior usando"X" como cualquier clase Cuadrado, Triangulo o Circulo y "Y" como la claseFiguraGeometrica, por lo tanto decimos que por ejemplo la clase Trianguloes de tipo FiguraGeometrica, en Java esto lo representamos asi: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class FiguraGeometrica{
}
class Triangulo extends FiguraGeometrica {
}
public class Principal{
public void metodo(){ /**Puedo crear objetos polimorficos*/ /**Objeto Triangulo de tipo FiguraGeometrica*/ FiguraGeometrica triangulo=new Triangulo(); } }
Vemos que FiguraGeometrica es la superClase y Triangulo es la clase hija o subClase, y por medio del polimorfismo podemos crear una instancia deTriangulo de tipo FiguraGeometrica...
Algunas Consideraciones.
(Estas consideraciones fueron tomadas de la revista digital JavaWord pues me parecen muy claras a la hora de trabajar con polimorfismo.)
Como en todo, tenemos unas reglas que se deben cumplir y tener en cuenta cuando vamos a trabajar con objetos polimorficos, estas son : Una variable de referencia puede ser de un solo tipo, y una vez que fue declarada, ese tipo jams puede modificarse..... por ejemplo, si declaramos triangulo de tipo FiguraGeometrica, no podemos decir mas adelante que el mismo objeto triangulo es de tipoFiguraPuntiaguda... Una referencia es una variable, de manera que puede ser reasignada a otros objetos (a menos que se declare como final). por ejemplo podemos hacer lo siguiente: 1 2 3 4 5 FiguraGeometrica miFiguraGeometrica = new FiguraGeometrica(); Cuadrado miCuadro=new Cuadrado();
/**Puedo crear objetos polimorficos, asignando su referencia*/ miFiguraGeometrica=miCuadro; Una variable de referencia puede tomar como referencia cualquier objeto del mismo tipo, o un subtipo del mismo..... va muy ligada a la anterior, pero nos dice que si por ejemplo tenemos la clasecuadroPequeo que es subClase de cuadro, al ser "nieta" deFiguraGeometrica, si se crean instancias de ella, se pueden reasignar a instancias de FiguraGeometrica... Un tipo de variable de referencia determina los mtodos que pueden ser invocados sobre el objeto que la variable referencia.... Trianguloal ser de tipo FiguraGeometrica puede acceder no solo a los mtodos de la clase Triangulo sino tambin a los deFiguraGeometrica (Claro, pues tiene que existir una relacin de Herencia entre ellos) Una variable de referencia puede tener como tipo el de una interface. Si es declarada de esta manera, podr contener cualquier clase que implemente la interfaz..... las interfaces tambin permiten el uso de herencia, por lo tanto podemos crear objetos usando para esto una interfaz, por ejemplo si FiguraGeometrica fuera una interface, lo anterior seria igual..... (esto tambin aplica para las clases Abstractas).
Como mencionamos en entradas pasadas, las clases abstractas y las interfaces (al ser clases completamente abstractas) no pueden ser instanciadas, o no directamente, la nica forma de hacerlo es mediante la herencia, ya que as extendemos sus funcionalidades creando objetos referenciando clases pero siendo del tipo de su superClase (abstracta o interface)
Hasta aqu la parte terica, espero que sea de utilidad..................... y en laprxima entrada veremos un ejemplo simple de como aplicar este concepto mediante un ejemplo en Java!!!
Ejemplo de Polimorfismo En Java En esta entrada vamos a trabajar un ejemplo rpido 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 mtodos abstractos de Animal sino tambin el mtodo comunicarse() de la interfaceIAnimal.......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, estn obligadas a implementar sus mtodos......... 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:
/** * Mtodo Comunicarse, sera implementado por las clases concretas * que hereden de la clase Animal */ public void comunicarse();
} La Interface IAnimal posee el mtodo comunicarse() el cual es completamente abstracto, evidenciamos que no es necesario indicarlo mediante la palabra abstract...........De la misma forma tenemos el atributovalor el cual (al ser declarado en la interface) se comporta como una Constante, as que nunca va a cambiar (en la entrada sobre Interfacesindicamos el porqu de estas propiedades)....
/** * 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 implementacin depende * de las clases concretas que extiendan la clase Animal */ public abstract void tipoAnimal();
}
Como vemos tenemos la clase Abstracta que implementa la Interface IAnimalpero como mencionamos al principio, esta clase no esta obligada a implementar el mtodo comunicarse() ya que tambin es clase abstracta.
Tenemos el mtodo tipoAnimal() el cual si debe ser declarado como abstracto, evidenciamos tambin 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 Encapsulacin (pero no de la forma ideal, podemos ver una pequea definicin en la entrada sobre conceptos Bsicos).
/** * 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"); } }
/** * @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 mtodo tipoAnimal(), y como Animal implementa la interface IAnimal, entonces tanto Gato como Perro al ser clases concretas estn obligadas a implementar el mtodo comunicarse()....
En las clases tambin 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.
/**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 creacin 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 aplicacin del polimorfismo, pero esto tambin 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 cdigo... 1 2 3 4 5 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 posicin 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 tipoPlanta, esto nos arrojara error, ya que planta no debera hacer parte de la Jerarqua 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 adems tambin evidenciamos la aplicacin de otros conceptos combinando algunos como la Herencia, Clases Concretas, Clases Abstractas, Interfaces.
Podemos resaltar el mtodo comunicarse() que heredan las clases Perro yGato, donde al ser un mtodo abstracto nos permite dar la implementacin que queramos dependiendo de quien lo use, entonces podemos ver que tantoperro como gato se comunican pero de forma distinta y esa diferencia se ve en nuestra implementacin...
En general vimos la importancia de trabajar con un paradigma Orientado a Objetos, pues nos da facilidades tanto a nivel de optimizacin como a nivel de estructura y lgica de la aplicacin, as como brindar claridad en los principales conceptos en torno a la POO...
Mas adelante nos adentraremos en el mundo de los Patrones de Diseo, donde se podrn evidenciar y aplicar los conceptos vistos nuevamente....