Objetivo |
Aprender cómo utilizar herencia y algunas otras cualidades de la orientación a objetos. | |
Producto a Entregar |
Un archivo comprimido con el programa generado en la actividad. | |
Forma de Trabajo |
Equipos | |
Tiempo estimado |
1 hora | |
Forma de Entrega |
Por Blackboard | |
Recomendaciones |
|
Instrucciones |
|
|---|---|
Este laboratorio es una continuación del laboratorio anterior. Sin embargo deberás entregar los dos laboratorios. No debes comenzar a resolver este laboratorio hasta haber terminado y enviado el laboratorio anterior.Paso 1:En este paso vamos a realizar las siguientes actividades:
Descarga las siguientes imágenes que vamos a utilizar en el laboratorio:
Y ponlas en el directorio que se ve en la siguiente foto (dentro de la carpeta de tu proyecto que en este caso es Sesion11).
En el laboratorio anterior hicimos una jaula que utilizaba objetos tipo String para guardar el nombre del animal que tenía adentro, eso es una solución que funciona pero que no es muy eficiente por varias razones:
Estos problemas se resuelven utilizando herencia. Podemos decir que la caja tiene dos animales, sin importar qué tipo de animales sean y luego podemos decir que los perros y los gatos son tipos de animales. De esta manera nuestro programa podría realizar validaciones mucho más complicadas con mucha menos complejidad. Además, tendremos un enfoque mucho más orientado a objetos porque una jaula no tendría dos String sino tendría literalmente dos animales. Paso 2:En este paso vamos a realizar las siguientes actividades:
Una ventaja más del enfoque más orientado a objetos es que podemos utilizar algunas propiedades que tienen todos los animales para hacer que nuestro programa sea mucho más vistoso. Para empezar, debemos eliminar la clase Cage del proyecto, haciendo click derecho sobre ella y seleccionando delete. NOTA: No borres la clase Cage hasta que hayas mandado el laboratorio anterior. Una vez que la hayas borrado no puedes recuperarla. Aunque en BlackBoard se queda guardada una copia puedes hacer un respaldo en caso de que lo necesites.
Ahora vamos a agregar una nueva clase Cage pero gráfica, selecciona el paquete data y haz click derecho. En el menú selecciona la opción New -> Bean Form. El nuevo Bean vamos a llamarlo CageBean y va a extender la clase javax.swing.JComponent.
Paso 3:En este paso vamos a realizar las siguientes actividades:
Ahora también vamos a crear la clase Animal que va a definir cómo deben ser todos los animales. Selecciona el paquete data y haz click derecho. En el menú selecciona la opción New -> Java Class, ponle de nombre Animal. Esta clase debe ser una clase abstracta. Una clase abstracta no se puede instanciar (es decir, no pueden existir objetos de esa clase) y sólo sirve para que otras clases la utilicen como super clase. En este momento podemos verlo como que existen perros, gatos, pericos, tortugas y todos ellos son animales, pero no existe algo que sólo sea animal y no pertenezca a una sub clase, es decir, todos tienen un tipo. Podemos hacer que una clase sea abstracta agregando la palabra clave abstract a la definición de la clase.
Una vez que hemos declarado la clase abstracta vamos a poner los atributos que deben compartir todos los animales. Los animales deben de tener una raza y una edad (recuerda que eran los atributos que tenían los perros y los gatos en el laboratorio anterior). Esta vez, las variables no las vamos a declarar private como habíamos hecho hasta ahora, sino que vamos a utilizar la palabra clave protected. Las variables que tienen la palabra clave protected son aquellas que son privadas para todos los demás menos las clases hijas, podríamos decir que estos atributos se los heredan a sus hijos. Tomando esto en cuenta podemos crear los atributos y el constructor:
¿Por qué implementamos un constructor si habíamos quedado que una clase abstracta no se podía instanciar? Muy sencillo, para ahorrar código, ahora que implementamos este constructor podemos evitarnos escribirlo en cada animal que creemos. Ahora vamos a declarar un método abstracto. Los métodos abstractos son aquellos que la super clase no implementa, pero que obliga a que sus hijos los implementen. En este caso sabemos que todos los animales pueden hablar, aunque algunos hablan ladrando y algunos maullando. Para crear el método abstracto speak() utiliza el siguiente código:
Además del método speak() vamos a crear otro método abstracto llamado paintAnimal() utilizando el siguiente encabezado: paintAnimal(Graphics g, int x, int y) Recuerda utilizar Fix Imports para agregar el import de Graphics. Por último genera los getters y setters (recuerda que no hay setAge() sino la edad se incrementa con el método birthday())de tu clase Animal y ya estamos listos para hacer que el perro y el gato la hereden. Paso 4:En este paso vamos a realizar las siguientes actividades:
Ahora ya terminamos de escribir la clase Animal, así que abre la clase Dog, borra todo lo que está dentro de la clase
Ahora escribe lo siguiente (fíjate en el extends, que va antes de la llave que inicia la clase):
La palabra clave extends nos dice que Dog es una clase de tipo Animal y por lo tanto va a tener todos sus métodos, es decir, Dog es una sub-clase de Animal. Después de escribir este código podrás ver que te marca un error. Analiza qué dice el error:
Paso 5:En este paso vamos a realizar las siguientes actividades:
¿Recuerdas que creamos un método abstracto que tenían que implementar todas las clases hijas? Lo único que te está diciendo NetBeans es que todavía no has implementado ese método en la clase Dog. Pon el cursor dentro del código de esta clase y presiona Ctrl+Space para que aparezca el diálogo de autocompletar. Escribe speak y aparecerá el siguiente menú en el que debes seleccionar la opción que dice implement.
Aparecerá el código del método listo para que lo implementemos. Pon las líneas necesarias para que al hablar un perro escriba "Guau!". Ahora haz lo mismo para agregar el otro método abstracto paintAnimal(). Dentro de este método escribe el siguiente código:
El método getClass().getResource() nos permite leer archivos que se encuentran dentro del directorio de nuestra aplicación. El método únicamente dibuja la imagen del perro al ser invocado. Recuerda utilizar Fix Imports para agregar todos los imports necesarios. Una vez que tenemos esto debemos crear un constructor para la clase Dog que lo único que va a hacer es llamar al constructor de la super clase (recuerda que lo habíamos creado para escribir menos). Escribe lo siguiente dentro de esta clase:
Como puedes ver el constructor es igual que antes pero ahora utilizamos la palabra clave super. Esta palabra clave sirve para que los hijos se comuniquen con la clase padre, por ejemplo, escribe super. para que aparezca el diálogo de auto completar y podrás observar que aparecen las propiedades de la super clase (como age y race). En este caso utilizamos la palabra clave super con los paréntesis para mandar llamar el constructor y pasarle como parámetro los parámetros que pedimos.
Compara la cantidad de código que tiene tu clase Dog ahora contra la que tenía antes (toma en cuenta que agregaste el método que va a dibujar al perro) y como puedes observar se reduce considerablemente. Compila tu código para verificar que no haya ningún error. Puedes utilizar la consola con algunos de los ejemplos que vimos la clase pasada para verificar que la clase Dog funcione correctamente (recuerda cambiar el método bark() por el método speak()). Paso 6:En este paso vamos a realizar las siguientes actividades:
Vamos a regresar a la clase CageBean para probar lo que hemos hecho hasta ahora. Agrega el siguiente código dentro de la clase CageBean:
Aqui podemos ver que la jaula no contiene objetos de tipo String sino contiene dos objetos de tipo Animal, con lo que el programa se vuelve mucho más natural (una jaula contiene animales). También podemos ver por primera vez el uso de la palabra clave null, que nos permite saber si un objeto existe (cuando todavía no agregamos ningún animal a la jaula los animales dentro de la jaula "no existen"). Más adelante veremos si los animales que se encuentran en la jaula existen o son null y con esto podremos saber si podemos agregar y si debemos dibujarlos. el método setPreferredSize() nos permite decirle a Java cuánto espacio queremos que ocupe nuestro CageBean de preferencia en una ventana, como en este caso tenemos los dos dibujos de los animales nos interesa que el tamaño sí se respete y por eso lo utilizamos. Antes de comenzar a codificar los métodos más complicados debemos crear los getters para nuestros dos objetos Animal. Crea el método getAnimal1() y getAnimal2() que devuelven un animal. Al igual que en el laboratorio anterior, queremos que nuestra clase jaula maneje los animales que se encuentran dentro, por lo que no vamos a crear setters. Una vez que hayas creado los getters agrega el método paintComponent() como se ve en la siguiente imagen:
Fíjate que varias líneas de código son muy similares, esta vez hemos puesto varias líneas diferentes, pero más adelante veremos cómo automatizar este tipo de comportamiento con ciclos. El método dibuja la jaula y después revisa si los animales existen, en caso de que así sea les indica que deben dibujarse (utilizando el método paintAnimal()). Antes de poder probar nuestra clase debemos implementar el método con el que vamos a agregar animales. ¿Recuerdas que antes debíamos agregar dos métodos diferentes porque manejabamos dos clases? En este método podemos ver muy clara la abstracción, en el método ponemos un animal en la jaula y no nos preocupamos de que clase de animal es.
Paso 7:En este paso vamos a realizar las siguientes actividades:
Con todo esto en su lugar compila el programa para verificar que no haya ningún error, después crea un JFrame al que llamarás MainFrame dentro del paquete sesion11 y agrega tu CageBean a la paleta para poderlo poner en este JFrame. Dentro del constructor de la clase MainFrame debes poner el siguiente código para probar que todo funcione (recuerda agregar los imports).
También recuerda agregar la línea new MainFrame() dentro del método main() de la clase Main. Es importante que te fijes que el constructor recibe como nombre del perro Beagle, de esta manera nos vamos a asegurar que dentro de la caja realmente se guarde este perro. Compila tu código y córrelo, deberá aparecer una ventana similar a la siguiente:
Fíjate que aparece el nombre Beagle, que es el mismo que le dimos en el constructor en la parte de arriba, si quisieramos utilizar algún método o quisieramos hacer modificaciones (que al estar en la jaula por mucho tiempo el perro se ponga triste) podríamos cambiar directamente el objeto, esta es otra ventaja muy importante de la orientación a objetos que se utiliza muchísimo en particular al crear listas porque nos permite guardar muchísima información en un solo objeto. Por analogía vamos a crear la clase Cat, recuerda que ahora sólo es necesario modificar algunas líneas de la manera siguiente:
Una vez que hayas terminado la clase Cat puedes volver a probar tu programa con el siguiente código:
Al correr el programa podremos ver que los animales ya se dibujan de manera correcta, pero todavía tenemos un problema, porque habíamos dicho que en caso de que hubieran un perro y un gato debería haber una pelea. Esto lo podemos lograr de dos maneras, podemos revisar al agregar los animales si son de cierto tipo, o podemos seleccionar un enfoque más orientado a objetos y hacer que el mismo objeto nos diga si pelearía con un animal. Paso 8:En este paso vamos a realizar las siguientes actividades:
Vamos a utilizar el segundo enfoque, por lo que vamos a tener que cambiar la clase Animal para que incluya otro método abstracto:
Y las clases Dog y Cat tendrán que implementarlo. En este método también vamos a ver un truco que se utiliza con mucha frecuencia para método que deben evaluar una situación y pueden devolver algo además de verdadero y falso (en este caso el método puede decirnos que van a pelear y gana el otro, que van a pelear y gana este o que no van a pelear). Como puedes observar el método nos va a devolver un int, por lo que podemos interpretar el valor que regrese el método y si es negativo, decir que pelearon y ganó el otro, si es cero no pelearon y si es positivo pelearon y perdió el otro. Es decir que para la clase Dog:
Como puedes ver instanceof nos permite saber de qué tipo es un objeto general (en este caso nos permite saber si la clase Animal que nos pasaron como parámetro es un perro o un gato). De la misma manera implementamos el del gato:
Como puedes ver en este caso el gato pierde contra el perro, por lo que devuelve -1 y en caso de que no sea un perro el gato no pelea con nadie. Volviendo a la clase CageBean deberíamos hacer que al agregar un animal revise si van a pelear.
Compila el código y prueba cómo puedes agregar animales, y cómo pelean. ¿Qué tendríamos que hacer si quisieramos agregar un ratón que pelea contra el gato y siempre pierde pero es ignorado por el perro? Tendríamos que agregar la clase Mouse, e implementar los métodos abstractos, después tendríamos que modificar el método fight() de la clase Cat para que siempre le gane al ratón y ya. Podríamos agregar tantos animales como quisíeramos con sólo cambiar algunas líneas de código. Como podemos ver, implementar clases y crear objetos puede parecer complicado y tedioso, pero una vez que lo implementamos bien nos ahorra enormes cantidades de tiempo y de esfuerzo, por lo que es importante utilizar todas las herramientas que están a nuestra disposición. Comprime tu carpeta de trabajo y mándala por Blackboard. |
|