{"id":2357,"date":"2016-02-22T06:55:57","date_gmt":"2016-02-22T05:55:57","guid":{"rendered":"http:\/\/karstieltopia.com\/?p=2357"},"modified":"2016-02-22T06:55:57","modified_gmt":"2016-02-22T05:55:57","slug":"herencia-y-jerarquia","status":"publish","type":"post","link":"http:\/\/karstieltopia.com\/programacion\/java\/herencia-y-jerarquia\/","title":{"rendered":"Herencia y jerarqu\u00eda"},"content":{"rendered":"

Anteriormente hemos visto que son las clases (aqu\u00ed<\/a>) y tambi\u00e9n hemos visto algunos detalles sobre la clase String usando ejemplos (aqu\u00ed<\/a>) pero hay cosas m\u00e1s importantes que tendr\u00edamos que saber sobre las clases antes de poder trabajar con ellas. Los conceptos m\u00e1s importantes son la herencia y jerarqu\u00eda.
\n\"Herencia
\n
\nLas clases de Java, la \u00faltima frontera. M\u00e1s o menos es lo que deber\u00edamos pensar, porque todo el tiempo que estemos cerca del mundo de Java estaremos viendo clases y herencia por todas partes.<\/span><\/p>\n

Y s\u00ed, ha llegado el temible momento en que aprenderemos como podemos tener cosas de un tipo \u00a1\u00a1\u00a1pero que a la vez son de otro tipo!!! Es decir, como he dicho anteriormente, magia negra.<\/span><\/p>\n

Uno de los conceptos m\u00e1s importantes de la POO (programaci\u00f3n orientada a objectos) es la herencia, la cual nos permite reusar un mont\u00f3n de c\u00f3digo de una manera correcta. B\u00e1sicamente esto significa que algunas clases estar\u00e1n basadas en otras clases y su relaci\u00f3n ser\u00e1 una relaci\u00f3n de jerarqu\u00eda, siendo siempre el primer elemento de todas las jerarqu\u00edas la clase Object.<\/p>\n

Siempre he pensado que la mejor manera de entender las cosas es con un ejemplo, as\u00ed que aqu\u00ed vamos a ver un ejemplo de herencia en d\u00f3nde podremos ver como se va estructurando la jerarqu\u00eda entre las clases que creemos.<\/p>\n

Aqu\u00ed tenemos un interfaz. Un interfaz es una clase especial que solamente tiene la firma de los m\u00e9todos y campos y es muy \u00fatil porque nos permite crear una buena jerarqu\u00eda entre nuestras clases, dado que no es posible instanciar un objeto directamente y obliga a que sus implementaciones tengan los mismos m\u00e9todos y campos con el c\u00f3digo que consideremos oportuno.<\/p>\n

En este caso, este interfaz tiene solamente un m\u00e9todo, getWheels, que devuelve un valor de tipo int y que no tiene ning\u00fan par\u00e1metro.<\/p>\n

public interface VehicleDesign {\r\n    int getWheels();\r\n}<\/pre>\n

Lo siguiente es una clase abstracta. Este es otro tipo especial de clase que se parece bastante m\u00e1s a una clase de las que hemos visto anteriormente pero que no es posible crear un objeto a partir de \u00e9l.<\/p>\n

Si miramos el c\u00f3digo de abajo, veremos que tenemos un “implements VehicleDesign” junto al nombre de la clase. Esto significa que implementar\u00e1 la definici\u00f3n del interfaz VehicleDesign, es decir, tendr\u00e1 los mismos m\u00e9todos y variables que su padre.<\/p>\n

Una de las mayores ventajas que tienen las clases abstractas es que son muy \u00fatiles para compartir m\u00e9todos con sus hijos.<\/p>\n

public abstract class Vehicle implements VehicleDesign {\r\n    int wheels;\r\n\r\n    public Vehicle (int number) {\r\n        this.wheels = number;\r\n    }\r\n\r\n    public int getWheels() {\r\n        return wheels;\r\n    }\r\n}<\/pre>\n

Y ahora veremos dos hijos de las clase que hemos visto previamente. La clase Car es un hijo de la clase Vehicle y hereda todo el contenido de su padre. Esto no es del todo real, porque depender\u00eda de la visibilidad de cada m\u00e9todo y de cada variable, pero por ahora nos sirve como aproximaci\u00f3n (supondremos que todos los m\u00e9todos y campos son de tipo “public”) y ya hablaremos de este tema en una pr\u00f3xima entrega.<\/p>\n

Lo que vemos al observar la clase es que extendemos la clase abstracta Vehicle que hab\u00edamos declarado anteriormente y esto lo hacemos con la palabra reservada “extend” y el nombre de su antecesor.<\/p>\n

Dentro de esta clase, nosotros podemos llamar directamente al m\u00e9todo getWheels porque es una parte de su definici\u00f3n, ya que lo hereda de su padre. De la misma manera se podr\u00eda hacer con cualquier otro m\u00e9todo o campo que tuviera. En otras entradas hemos visto lo que es un constructor<\/a>, pero ahora que estamos hablando de los hijos y de herencia, quiz\u00e1s pensemos que funcionan de manera diferente, pero la realidad es que el funcionamiento es el mismo salvo por el detalle de que podemos llamar al constructor de su clase padre a trav\u00e9s del comando “super”. En este ejemplo, llamamos al constructor del padre pas\u00e1ndole el valor de 4.<\/p>\n

public class Car extends Vehicle {\r\n\r\n    public Car() {\r\n        super(4);\r\n    }\r\n\r\n    public boolean isFerrari() {\r\n        return false;\r\n    }\r\n}<\/pre>\n

Y esta otra clase, Motorbike, es tambi\u00e9n una hija de la clase Vehicle y llamamos al constructor del padre con el valor de 2.<\/p>\n

public class Motorbike extends Vehicle {\r\n\r\n    public Motorbike () {\r\n        super(2);\r\n    }\r\n\r\n}<\/pre>\n

Ahora que ya tenemos definida nuestra estructura de datos, vamos a ver unos cuantos ejemplos sobre como funciona la herencia en Java entre estas clases. Si miramos la clase siguiente, clase Main, vemos que solamente tiene un m\u00e9todo main que usaremos para poder hacer pruebas con las clases que hemos ido definiendo. Tambi\u00e9n veremos que hay algunas l\u00edneas que est\u00e1n comentadas (si no recuerdas que son los comentarios… \u00e9chale un vistazo a esta entrada donde explico que son los comentarios<\/a>). Estas l\u00edneas comentadas son l\u00edneas que est\u00e1n mal pero que las he dejado porque creo que son muy explicativas de ciertas situaciones que nos podemos encontrar.<\/p>\n

public class Main {\r\n    public static void main (String args[]) {\r\n        Car car1 = new Car();\r\n        System.out.println(\"Car1:\" + car1.getWheels());\r\n        System.out.println(\"Car1:\" + car1.isFerrari());\r\n\r\n        \/\/ Vehicle car2 = new Vehicle(); Error because Vehicle is an abstract class and it is not possible to instance it\r\n\r\n        Vehicle car3 = new Car();\r\n        System.out.println(\"Car3:\" + car3.getWheels());\r\n        \/\/ System.out.println(car3.isFerrari());  Error because Vehicle doesn\u00b4t have that method\r\n        System.out.println(\"Car3:\" + ((Car)car3).isFerrari());\r\n\r\n        Vehicle motorbike1 = new Motorbike();\r\n        System.out.println(\"Motorbike1:\" + motorbike1.getWheels());\r\n\r\n        \/\/ Vehicle motorbike2 = new VehicleDesign(); Error because it is not possible to instance an interface\r\n\r\n        \/\/ VehicleDesign motorbike3 = new Vehicle();  Error because Vehicle is an abstract class and it is not possible to instance it\r\n\r\n        VehicleDesign motorbike4 = new Motorbike();\r\n        System.out.println(\"Motorbike4:\" + motorbike4.getWheels());\r\n\r\n    }\r\n}<\/pre>\n

La primera secci\u00f3n<\/strong>\u00a0es sobre el objeto car1. Aqu\u00ed vemos un ejemplo normal de como creamos el objeto car1 a partir de la clase Car y tenemos dos salidas a consola, una que ser\u00e1 “Car1: 4” y otra que es “Car1: true”. Si nos fijamos en este ejemplo, a efectos funcionales no estamos viendo nada sobre herencia, solo que parece que tenemos el c\u00f3digo del padre en el hijo.<\/p>\n

La segunda secci\u00f3n<\/strong>\u00a0es sobre car2. La l\u00ednea est\u00e1 comentada porque est\u00e1 mal pero, \u00bfpor qu\u00e9 est\u00e1 mal? B\u00e1sicamente es que estamos intentando crear un objeto directamente utilizando el constructor de una clase abstracta, lo cu\u00e1l est\u00e1 mal por la propia definici\u00f3n que da una clase abstracta: no se puede instanciar directamente.<\/p>\n

La tercera secci\u00f3n<\/strong>\u00a0es sobre el objeto car3. Aqu\u00ed vemos algo bastante raro: “Vehicle car3 = new Car()”. \u00bfC\u00f3mo es que estamos creando un objeto de tipo Vehicle con el constructor de Car? La respuesta se haya f\u00e1cilmente en la herencia y es que Car es un Vehicle y este es su padre y todos los hijos de una clase son del tipo de su padre, de ah\u00ed que podamos crear un objeto de tipo Vehicle (inclusive cuando es una clase abstracta).<\/p>\n

De acuerdo, si lo ejecutamos veremos que imprimimos el n\u00famero de ruedas (4, porque el objeto creado es un coche, Car, y por tanto hemos llamado al constructor de la clase padre con el par\u00e1metro acorde gracias a que tenemos la herencia definida) pero entonces, \u00bfpor qu\u00e9 est\u00e1 la siguiente l\u00ednea comentada?<\/p>\n

La respuesta es sencilla, el motivo de esto es que el m\u00e9todo isFerrari() est\u00e1 solamente definida en la clase Car, no en la clase Vehicle y por tanto si creamos un objeto de tipo Vehicle, aunque lo hayamos hecho usando el constructor de Car, no disponemos en su definici\u00f3n de ese m\u00e9todo. As\u00ed que nos toca recordar que solamente podemos llamar directamente a aquello que tenemos definido, aunque el constructor sea otro que tenga definidas otras cosas.<\/p>\n

Pero (siempre hay un pero), vemos que hay otra l\u00ednea m\u00e1s. Y es que aqu\u00ed podemos utilizar de nuevo magia negra y podemos comprobar si es un ferrari o no. \u00bfQu\u00e9 como lo hacemos? Pues con un bonito (o m\u00e1s bien feo) truco con el que forzamos a Java a que interprete un tipo diferente del que realmente es.<\/p>\n

B\u00e1sicamente, nosotros estamos dici\u00e9ndole a Java que somos muy valientes y que nos atrevemos a que aunque todo diga que es un objeto de tipo tal, usemos otro tipo, con todas las consecuencias que eso tiene. La manera de hacerlo es muy sencilla, solamente tenemos que poner entre par\u00e9ntesis el tipo de clase que queremos que interprete delante del objeto en cuesti\u00f3n: (clase)objeto<\/em>. En el ejemplo es\u00a0“((Car)car3).isFerrari()”, de manera que car3 se vuelve durante un instante un objeto de tipo Car y entonces podemos llamar a todos los m\u00e9todos de ese tipo, es decir, ahora podremos comprobar si es un ferrari o no.<\/p>\n

Este truco nos ofrece muchas posibilidades, pero tenemos que tener mucho cuidado con \u00e9l, porque al estar forzando a Java que crea que algo es de un tipo perdemos todas las comprobaciones que hace en el momento de compilaci\u00f3n, as\u00ed que si est\u00e1 mal, nos explotar\u00e1 durante la ejecuci\u00f3n mediante una excepci\u00f3n (qu\u00e9 tambi\u00e9n veremos en el futuro). Una forma de controlar esto es que, antes de hacer nada raro, comprobemos si es de ese tipo o no mediante la palabra reservada instanceof<\/em> (y s\u00ed, tambi\u00e9n hablaremos sobre eso en otro post).<\/p>\n

La cuarta secci\u00f3n<\/strong>\u00a0es sobre motorbike1. Aqu\u00ed nos encontramos con la misma situaci\u00f3n que en la secci\u00f3n tres, salvo que es un objeto creado a partir de un constructor de Motorbike. Es posible hacer esto por la herencia de la clase Vehicle.<\/p>\n

La quinta secci\u00f3n<\/strong>\u00a0es sobre motorbike2\u00a0y est\u00e1 mal porque est\u00e1 intentando crear un objeto de tipo Vehicle utilizando el constructor de la interfaz VehicleDesign, lo cu\u00e1l est\u00e1 mal porque ninguna interfaz puede ser utilizada para crear un objeto.<\/p>\n

La sexta secci\u00f3n<\/strong>\u00a0es sobre motorbike3\u00a0y est\u00e1 comentada porque intenta crear un objeto utilizando la interfaz VehicleDesign y el constructor de la clase abstracta Vehicle, lo cual no es posible porque no se pueden crear objetos utilizando una clase abstracta para ello.<\/p>\n

La s\u00e9ptima secci\u00f3n<\/strong>\u00a0es sobre motorbike4 y aqu\u00ed vemos que estamos creando un objeto utilizando la definici\u00f3n del interfaz VehicleDesign utilizando para ello el constructor de una clase que hereda de la clase que implementa dicho interfaz, en este caso Motorbike.<\/p>\n

Con todo el conocimiento que hemos visto aqu\u00ed sobre herencia y jerarqu\u00eda entre clases en Java, ahora podr\u00edas crear complejos hechizos de magia negra, dado que podr\u00e1s reutilizar mucho c\u00f3digo y estructuras de datos, con lo que todos tus desarrollos en Java mejorar\u00e1n ostensiblemente.<\/p>\n

Aunque no nos confiemos, aun quedan un mont\u00f3n de detalles que veremos en futuras entradas en el blog.<\/p>\n","protected":false},"excerpt":{"rendered":"

Anteriormente hemos visto que son las clases (aqu\u00ed) y tambi\u00e9n hemos visto algunos detalles sobre la clase String usando ejemplos (aqu\u00ed) pero hay cosas m\u00e1s importantes que tendr\u00edamos que saber sobre las clases antes de poder trabajar con ellas. Los conceptos m\u00e1s importantes son la herencia y jerarqu\u00eda.<\/p>\n","protected":false},"author":1,"featured_media":2358,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spay_email":"","jetpack_publicize_message":"Herencia y jerarqu\u00eda","jetpack_is_tweetstorm":false},"categories":[22],"tags":[995,996],"jetpack_featured_media_url":"https:\/\/i1.wp.com\/karstieltopia.com\/wp-content\/uploads\/2016\/02\/carandmotorbike.jpg?fit=500%2C333","jetpack_publicize_connections":[],"yoast_head":"\nHerencia y jerarqu\u00eda - Karstieltopia<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"http:\/\/karstieltopia.com\/programacion\/java\/herencia-y-jerarquia\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Herencia y jerarqu\u00eda - Karstieltopia\" \/>\n<meta property=\"og:description\" content=\"Anteriormente hemos visto que son las clases (aqu\u00ed) y tambi\u00e9n hemos visto algunos detalles sobre la clase String usando ejemplos (aqu\u00ed) pero hay cosas m\u00e1s importantes que tendr\u00edamos que saber sobre las clases antes de poder trabajar con ellas. Los conceptos m\u00e1s importantes son la herencia y jerarqu\u00eda.\" \/>\n<meta property=\"og:url\" content=\"http:\/\/karstieltopia.com\/programacion\/java\/herencia-y-jerarquia\/\" \/>\n<meta property=\"og:site_name\" content=\"Karstieltopia\" \/>\n<meta property=\"article:published_time\" content=\"2016-02-22T05:55:57+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/i1.wp.com\/karstieltopia.com\/wp-content\/uploads\/2016\/02\/carandmotorbike.jpg?fit=500%2C333\" \/>\n\t<meta property=\"og:image:width\" content=\"500\" \/>\n\t<meta property=\"og:image:height\" content=\"333\" \/>\n<meta name=\"twitter:card\" content=\"summary\" \/>\n<meta name=\"twitter:creator\" content=\"@karstiel\" \/>\n<meta name=\"twitter:site\" content=\"@karstiel\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"http:\/\/karstieltopia.com\/#website\",\"url\":\"http:\/\/karstieltopia.com\/\",\"name\":\"Karstieltopia\",\"description\":\"Programaci\\u00f3n, tecnolog\\u00eda y a\\u00f1adidos\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"http:\/\/karstieltopia.com\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"es\"},{\"@type\":\"ImageObject\",\"@id\":\"http:\/\/karstieltopia.com\/programacion\/java\/herencia-y-jerarquia\/#primaryimage\",\"inLanguage\":\"es\",\"url\":\"https:\/\/i1.wp.com\/karstieltopia.com\/wp-content\/uploads\/2016\/02\/carandmotorbike.jpg?fit=500%2C333\",\"width\":500,\"height\":333,\"caption\":\"Herencia y jerarqu\\u00eda\"},{\"@type\":\"WebPage\",\"@id\":\"http:\/\/karstieltopia.com\/programacion\/java\/herencia-y-jerarquia\/#webpage\",\"url\":\"http:\/\/karstieltopia.com\/programacion\/java\/herencia-y-jerarquia\/\",\"name\":\"Herencia y jerarqu\\u00eda - Karstieltopia\",\"isPartOf\":{\"@id\":\"http:\/\/karstieltopia.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"http:\/\/karstieltopia.com\/programacion\/java\/herencia-y-jerarquia\/#primaryimage\"},\"datePublished\":\"2016-02-22T05:55:57+00:00\",\"dateModified\":\"2016-02-22T05:55:57+00:00\",\"author\":{\"@id\":\"http:\/\/karstieltopia.com\/#\/schema\/person\/3d09a55c38c7c00e78c41fa3f71a6e75\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"http:\/\/karstieltopia.com\/programacion\/java\/herencia-y-jerarquia\/\"]}]},{\"@type\":\"Person\",\"@id\":\"http:\/\/karstieltopia.com\/#\/schema\/person\/3d09a55c38c7c00e78c41fa3f71a6e75\",\"name\":\"karstiel\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p6AuIG-C1","_links":{"self":[{"href":"http:\/\/karstieltopia.com\/wp-json\/wp\/v2\/posts\/2357"}],"collection":[{"href":"http:\/\/karstieltopia.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/karstieltopia.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/karstieltopia.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/karstieltopia.com\/wp-json\/wp\/v2\/comments?post=2357"}],"version-history":[{"count":3,"href":"http:\/\/karstieltopia.com\/wp-json\/wp\/v2\/posts\/2357\/revisions"}],"predecessor-version":[{"id":2369,"href":"http:\/\/karstieltopia.com\/wp-json\/wp\/v2\/posts\/2357\/revisions\/2369"}],"wp:featuredmedia":[{"embeddable":true,"href":"http:\/\/karstieltopia.com\/wp-json\/wp\/v2\/media\/2358"}],"wp:attachment":[{"href":"http:\/\/karstieltopia.com\/wp-json\/wp\/v2\/media?parent=2357"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/karstieltopia.com\/wp-json\/wp\/v2\/categories?post=2357"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/karstieltopia.com\/wp-json\/wp\/v2\/tags?post=2357"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}