Saltar navegación

2025-03-17-Programacion - Contenido educativo

Ajuste de pantalla

El ajuste de pantalla se aprecia al ver el vídeo en pantalla completa. Elige la presentación que más te guste:

Subido el 17 de marzo de 2025 por Jose Manuel M.

27 visualizaciones

Tareas de los temas 7 y 8

Descargar la transcripción

estábamos comentando aquí fuera de la grabación de dedicar la clase de hoy a hacer las tareas 00:00:02
lo repito un poco para que quede puesto en la grabación vale por si alguien lo ve luego fuera 00:00:08
de la tutoría las dos tareas que tenemos pendientes de resolver y luego como tenemos este tema así que 00:00:14
es un poquito más largo no sucede como el de excepciones que teníamos una única semana por 00:00:21
la semana que viene pegar un repaso así un poco un poco más en profundidad la semana que viene y 00:00:25
Y luego alguna otra semana que podamos dedicar un poco más en profundidad a lo que son los mecanismos estos para almacenar datos de forma dinámica, que viene a ser lo que habla de colecciones y mapas, y luego la división en conjuntos, bueno, pues diferentes cosillas por ahí. Esto lo tratamos, si os parece, la semana que viene. 00:00:29
No sé si antes de arrancar a resolver las dos tareas, queréis, los que estéis conectados, hacerme alguna pregunta o algo antes de arrancar. Si tenéis alguna propuesta de pregunta, pues bueno, pues es un buen momento y si no, pues empezamos a resolver la primera de las tareas. 00:00:50
nada, bueno, pues 00:01:09
pues nada, pues vamos al ataque, si os surge 00:01:14
luego alguna cosita, ya me vais diciendo 00:01:16
a ver, pues vamos a ver 00:01:18
el enunciado, venimos por aquí 00:01:22
a nuestro curso, programación grupo B 00:01:24
y bueno, las dos que nos quedan pendientes 00:01:26
son las del tema 7 y tema 8 00:01:33
tenéis una solución a la 00:01:34
tarea abierta en las dos, como en todos 00:01:38
los temas, una 00:01:40
propuesta de solución al enunciado 00:01:41
lo que vamos a hacer hoy 00:01:44
va a ser prácticamente, pues una réplica 00:01:46
más o menos parecida, no sé si según vayamos haciéndolo nos vendrá 00:01:49
alguna variante, pero será algo muy parecido porque tanto esa solución 00:01:52
como lo que vamos a hacer ahora pretende resolver el ejercicio. 00:01:56
La del tema 7, que es este que teníamos como utilización avanzada 00:02:00
de clases, en verdad, como al trabajar con un lenguaje 00:02:04
orientado a objetos, desde el minuto 1, pues ya tienes 00:02:09
que poner el nombre de una clase con la etiqueta class y 00:02:12
Y bueno, por las referencias de si son públicos o no son públicos y todas estas cosas, pues empezamos a hablar de clases en un tema en particular, que es el TESOL 4, pero desde el minuto 1 realmente ya las estamos trabajando. 00:02:16
Con lo cual, luego llegan momentos en los que al trabajar estos temas lo que hacemos es consolidar o formalizar cosas que hemos ido viendo ya con anterioridad, que es un poco lo que nos va a pasar ahora en este tema. 00:02:29
Mirad, en este tema lo que habíamos estado hablando, entre algunas de las características que tienen las programaciones orientadas a objetos, pues está la de poder definir interfaces, la de poder definir métodos abstractos y la de la herencia. 00:02:44
Y sobre estas características de la programación orientada a objetos es sobre lo que trabaja, sobre lo que versa sobre todo este ejercicio. 00:03:05
Bueno, hace un par de años cuando esta tarea ya la teníamos el año pasado, hace un par de años, pues bueno, mis hijas estaban ahí súper enganchadísimas a los cromos de Pokémon y bueno, pues por hacerles un guiño se me ocurrió hacer este enunciado, ¿no? 00:03:14
entonces viene a decir el enunciado que en el mundo Pokémon 00:03:28
si hay alguien muy friki de aquí, lo mismo hay errores 00:03:31
porque yo no estoy tan enganchado como mis hijas 00:03:34
con lo cual igual al hacer el enunciado metía la pata en algo 00:03:37
puse estas cosas en función de lo que podía ir escuchando 00:03:40
en mi oreja por ahí cuando hablaban entre ellas 00:03:43
entonces viene a decir que en el mundo Pokémon Pikachu es uno de los personajes 00:03:45
más conocidos, bueno tiene mucho bla bla bla 00:03:50
aunque luego nos dice aquí en detalle cómo se traslada 00:03:52
al código la solución del ejercicio 00:03:55
Entre sus características destacan los niveles de energía para luchar, energía y vida. Dos valores que decimos que sean valores numéricos enteros y que de alguna forma provoquemos que no puedan ser negativos. 00:03:57
de aquí que es lo que conseguimos 00:04:12
bueno pues que si esto la vida 00:04:16
y la energía son características 00:04:19
de algo que vamos a definir un actor en nuestro programa 00:04:21
que va a ser Pikachu pues podremos definir una clase que sea Pikachu 00:04:25
que tenga como atributos de clase 00:04:28
acordaros los atributos son aquellas cosas que caracterizan a los objetos 00:04:30
de una determinada clase pues la energía y la vida 00:04:33
y decimos que tengan 00:04:37
valores numéricos enteros, con lo cual los podemos definir de tipo int. 00:04:40
Podríamos hacerlo long también, si quisiéramos valores muy grandes, bueno, pues con int 00:04:44
nos damos por satisfechos. Y por aquí nos dice que no puedan ser negativos. 00:04:48
Lógicamente, si definimos estos valores como int, ¿qué sucede? 00:04:52
Que los datos tipo int nos permiten efectivamente valores negativos. 00:04:55
Si queremos, desde nuestro código, bloquear 00:05:00
que en todo momento esos datos puedan ser negativos, ¿qué es lo que tenemos 00:05:04
que hacer? Pues recordad, vamos a definir los privados, así 00:05:08
si se instancian objetos de esta clase desde otras clases del programa 00:05:11
que queden fuera del alcance de nuestra programación, no van a poder 00:05:15
hacer directamente esos atributos y podemos definir 00:05:19
unos getter y unos setters que tengan 00:05:23
la suficiente lógica para evitar que sean negativos. Entonces en el setter vamos 00:05:27
a meter código para evitar este detalle. En el momento que 00:05:31
intente dar un valor de vida o de energía menor que cero por lo que vamos a hacer va a ser obligar 00:05:35
a que sea como mínimo un cero bueno pues pikachu que tendrá ser dos estos dos atributos los 00:05:41
ponemos privados y obligaremos a que no sean negativos en el setter luego dice por aquí que 00:05:50
raichu al oa y raichu canto son evoluciones de este si son evoluciones de este lo que nos está 00:05:57
invitando es que estos dos, pues vamos a tener 00:06:06
una clase de cada uno de estos dos y como son evoluciones 00:06:09
van a tener estas características, con lo cual podemos hacer 00:06:12
que tengan herencia de la clase Pikachu 00:06:15
o de la clase Pokémon. Dice, por otra parte, existen 00:06:18
entrenadores, bueno, y dice que 00:06:23
Alola es capaz, tiene la característica 00:06:26
de volar y Kanto no. Con lo cual, si ambos dos 00:06:29
son hijos a través de la herencia 00:06:32
de la clase Pokémon, los dos tendrán 00:06:35
una energía y tendrán una vida 00:06:38
y solamente, es decir, ambos dos 00:06:40
tendrán este atributo heredado y en la clase de Alola 00:06:45
pondremos un método que sea el método volar que no lo tendremos 00:06:48
disponible en canto. 00:06:51
Por otra parte, existen entrenadores cuya función es entrenar 00:06:53
que estos mejoren su nivel de energía. 00:06:56
Y aquí estoy forzando un poco el enunciado 00:06:59
para lo que por aquí dice. 00:07:02
Pues para poder definir también una interfaz, ya que era una de las cosas que teníamos trabajando en este ejercicio. La idea es que en el interfaz entrenador, recordad que los interfaces, lo que decíamos era que no identifican una serie de métodos, pero no los desarrollan. 00:07:04
¿Esto qué es lo que nos permite? Que todo aquel que digamos que implementa esa interfaz obligatoriamente tendrá que desarrollar esos métodos y cada uno podrá tener un desarrollo de ese método particular, cada uno hará unas determinadas cosas cuando entrene. 00:07:22
pero que nos garantiza si decimos que implementa esa interfaz 00:07:39
pues nos garantiza como que si firmase un contrato 00:07:43
la clase que dice que desarrolla esta interfaz 00:07:46
de que no va a quedar sin desarrollar ese método 00:07:48
el de entrenar 00:07:52
que es lo que sucede que en el contexto 00:07:54
en el enunciado general del proyecto 00:07:58
pues habrá sitios, en particular será desde aquí 00:08:00
desde la clase ejecutar pokemon 00:08:03
que tendrá que cubrir un requisito 00:08:06
en el cual podamos decir a los diferentes Pokémon que entrenen. 00:08:09
Si desde aquí tiene que existir un método que digamos a los diferentes Pokémon que entrenen 00:08:14
y no se lo obligamos a través de una interfaz, ¿qué puede suceder? 00:08:20
Pues que a lo mejor el Raichu Kanto este no implemente ese método 00:08:25
y el programa ya no quede correcto, porque de hecho no nos compilaría 00:08:29
si desde aquí intentamos llamar un método de entrenar que no existe aquí. 00:08:34
En el diseño general habría una especificación que diría, todos los Pokémon tienen que poder entrenar. 00:08:39
A un equipo de trabajo le encargo, por ejemplo, que haga el desarrollo de las clases Pokémon y de sus dos clases hijas. 00:08:48
Bajo ese acuerdo tendrán que disponer del método de entrenar. ¿Cómo obligo a esto? 00:08:57
pues en la clase Pokémon le digo que implemente esta interfaz, con lo cual ya nos garantizamos que todo hijo de Pokémon lo tendrá disponible. 00:09:01
Y luego, probablemente a otro equipo de trabajo, si fuera un proyecto muy grandote, podríamos decirle que haga el desarrollo de la clase EjecutarPokémon, 00:09:10
que como requisito general sabe que tiene la posibilidad, a través de la interfaz de las clases de los Pokémon y de sus hijos, 00:09:19
tiene la posibilidad de llamar a un método que es el método entrenar vale pues éste sabe que va a 00:09:26
estar disponible y en estos tiene que que va a estar disponible para ser llamado y en estos 00:09:31
tiene que estar disponible porque lo hemos implementado y nos hemos obligado por el 00:09:37
contrato que hemos firmado digamos de alguna manera al decir que implementa esta interfaz 00:09:41
bueno pues vamos a ir si os parece haciendo un poco el proyecto vamos a crear un proyecto que 00:09:47
se llame Pokémon, por ejemplo. Ahora después seguimos también leyendo el enunciado. 00:10:04
Una primera cosa, si os parece, que podemos hacer es definir esta interfaz. 00:10:23
Interfaz creo que nos decía que se llame entrenador. Vamos a verlo. 00:10:30
Efectivamente, entrenador. Pues nada, ahí lo tenemos. 00:10:36
El interfaz, normalmente en las clases, ya sabéis, ponemos aquí public class. 00:10:53
En este caso es un interfaz, pues ponemos public interface y lo que hace es entrenar. 00:10:56
Entonces podemos poner aquí un public que no devuelva nada, void, que se llame entrenar y recordad que en los interfaces no implementamos las cosas. 00:11:03
Si intentásemos implementarlo como en una clase normal, pues fijaros que directamente como no es la lógica propia de los interfaces, pues ya directamente ni siquiera me compila. 00:11:18
el IDE ya me dice, oye no, no me gusta esto 00:11:33
ahí lo tenemos, el interfaz entrenar 00:11:36
luego tiene, vamos a crear 00:11:43
una clase, que sea la clase 00:11:52
Pokémon o Pikachu 00:11:55
no sé cómo dice que se llame la clase 00:12:01
a ver, dice que la clase se llame 00:12:04
Pikachu, pues la llamamos Pikachu 00:12:07
pues ahí la tenemos, la clase 00:12:11
todo todo lo que sea un pokemon es decir pikachu sus herencias tendrá que considerar el interfaz 00:12:24
entrenador implement entonces el momento que digo que implemente esta interfaz lo que estoy 00:12:34
es diciendo que pikachu tiene que cumplir con el contrato que está haciendo a la hora de 00:12:45
implementar este interfaz que es desarrollar los métodos que tenga definidos el interfaz 00:12:52
De hecho, si me pongo aquí en el IDER, fijaros que lo que me sugiere es que añada los métodos que están sin implementar. 00:12:59
Entonces lo implemento aquí y de momento ya me compila. 00:13:07
Otra posibilidad es no dejarlo implementado aquí, implementarlo en las clases hijas que tenga. 00:13:16
Vamos a dejarlo así de momento aquí, sin meter ningún código. 00:13:24
Lo que vamos a hacer es implementarlo aquí en la clase padre y no en las clases hijas, sobrescribirlo si fuese necesario. 00:13:28
O implementar aquí en la clase padre un código que sea general para los dos y si le vale a los dos hijos lo que pase aquí, pues bien, vamos para adelante. 00:13:35
Y si no, en alguno de los hijos o en ambos, sobrescribir, que es otra de las características de la programación orientada a objetos, este método. 00:13:45
Eso ya es una cuestión de herencia y la posibilidad de sobrescritura de métodos. 00:13:52
A ver, mirad, nos dice por aquí que la clase Pikachu es una clase abstracta. El hecho de definir una clase abstracta normalmente va a ir de la mano de que va a tener métodos que van a estar sin implementar. 00:13:56
Solamente es posible tener clases abstractas si van a tener luego clases hijas. Una clase abstracta, si tenemos métodos que no están implementados, lógicamente de esa clase nunca vamos a poder instanciar objetos. 00:14:17
¿Cuál es la explicación de no poder instanciar objetos de una clase abstracta? 00:14:30
Pues si hay métodos en los que no pone qué tiene que pasar cuando invoquemos esos métodos, 00:14:33
lógicamente, si definiésemos un objeto de esa clase y el programa no lo permitiese, 00:14:39
al llamar esos métodos, el programa se quedaría con las manos arriba diciendo 00:14:44
¿y ahora qué tengo que hacer si no me lo han indicado? 00:14:48
Entonces, es cierto que es posible definir clases abstractas, 00:14:50
pero luego tendremos que implementar clases hijas y estas clases hijas 00:14:54
se verán obligadas a desarrollar aquellos métodos abstractos 00:14:57
que tenga la clase padre, es decir, algo parecido 00:15:01
a lo que nos acaba de suceder con el interfaz. 00:15:03
Un interfaz se podría considerar como una clase abstracta 00:15:07
donde todos sus métodos son abstractos, 00:15:10
es decir, no están desarrollados. 00:15:13
Bueno, pues aquí, aprovechando que está la clase padre, 00:15:18
es donde vamos a definir los métodos de energía y de vida, 00:15:21
de nivel de vida 00:15:25
de nivel de energía y de nivel de vida 00:15:28
que todo Pokémon va a tener 00:15:30
todo Pikachu, tanto el Alola 00:15:32
como el Kanto este 00:15:34
van a tener energía y vida 00:15:36
pues entonces en lugar de definirlo en cada uno de ellos 00:15:37
lo podemos definir en la clase padre 00:15:40
y que cada uno de ellos lo tengan de forma 00:15:42
heredada 00:15:44
entonces aquí podríamos decir 00:15:45
int y vida 00:15:47
int y energía 00:15:49
hemos dicho que 00:15:52
estos valores no nos interesa que tengan 00:15:57
datos negativos, pero lógicamente 00:15:59
un entero puede tener, no me acuerdo el rango exactamente, pero 00:16:13
puede tener valores desde un valor negativo muy alto hasta un valor 00:16:17
negativo muy bajo. Fijaros, si quisiéramos saber el rango 00:16:22
de valores que tiene, pues podríamos, llamando a la clase 00:16:25
en la clase integer, que es la clase grupper de 00:16:29
de lind podríamos el más value y el íntegra punto me envalúe si no no si no nos acordamos 00:16:35
de los datos no tenemos donde referenciar lo y solamente tenemos el envalúe porque no sale 00:16:44
cuando me sale creo porque esto no está compilando a ver ahí está pues haciendo un sistema print ln 00:16:59
de estos dos valores podríamos saber justo el rango con el que trabajamos que te permite un 00:17:13
entero. Justo el máximo valor o el mínimo valor tiene la clase 00:17:18
wrapper integer, la wrapper 00:17:21
la que envuelve los tipos primitivos 00:17:24
de datos int, pues podríamos conocer 00:17:27
el máximo valor que acepta un entero y el mínimo valor que acepta 00:17:30
el entero. En cualquier 00:17:33
caso, según dice el enunciado, podremos trabajar desde cero 00:17:36
hasta el más value bloqueando el minValue. 00:17:39
Si esto lo dejamos ahora mismo sin ninguna 00:17:42
una etiqueta de ámbito, pues tendría un ámbito 00:17:46
package, es decir, de cualquier clase 00:17:49
que esté en este mismo paquete, en este caso en el paquete 00:17:51
de por defecto, que la clase Pikachu, tendríamos 00:17:55
posibilidad de modificarlo. Y esas modificaciones 00:17:58
desde otras partes de código, que probablemente no estaríamos programando 00:18:01
nosotros, serían capaces de meter valores negativos, cosa 00:18:04
que no nos interesa. Si queremos bloquearlo para que 00:18:07
solamente se pueda modificar desde mi propia clase y así 00:18:10
y tener garantías totales de que si eso coge un valor 00:18:13
negativo es porque me he equivocado yo en este código que estoy desarrollando, pues lo 00:18:17
podemos hacer, recordad, es poner la etiqueta private, si ponemos la etiqueta private 00:18:21
ya el ámbito de 00:18:25
alcance de estas variables van a ser siempre dentro de la 00:18:29
clase Pikachu. Sí, lo podríamos poner protective 00:18:33
y entonces tendrían también las hijas, si, bueno, es 00:18:44
cerrar más la puerta, un poquito más o un poquito menos. 00:18:48
Bueno, como queráis. De tal forma, en realidad 00:18:52
si la ponemos private o protected 00:18:54
nos da un poco igual si ahora definimos los getter y los setter 00:18:57
y los hacemos públicos. Porque al hacer el getter y el setter 00:19:00
público, pues ya directamente a través de esos dos 00:19:03
métodos podemos acceder a este valor y me da igual que esto sea private 00:19:06
o no. Si nosotros estamos haciendo 00:19:09
el desarrollo de la clase de Pikachu y luego la 00:19:12
canto y la otra verdad que son hijas y las hacemos nosotros y desde ningún otro sitio vamos a tener 00:19:15
garantía de que se va a hacer de cara a ellas pues podríamos abrir un poquito más el abanico de acceso 00:19:21
a estas variables directamente bueno pues con protective si la ponemos privado pues ya sabéis 00:19:26
que es lo más cerrado solamente para esta clase pero ahora con los getter y los setter pues en 00:19:31
realidad podemos modificar y lo que sí que vamos a hacer va a ser en el setter tener garantías de 00:19:36
que el valor nunca sea negativo, que es lo que nos pide el ejercicio. 00:19:41
Entonces, para no tener que andar escribiendo mucho, 00:19:46
si nos venimos aquí, el Eclipse nos da, fijaros, 00:19:49
las mil cosas que nos permite hacer Eclipse. Estamos utilizando 00:19:53
siempre cuatro o cinco, en realidad, pero bueno, permite hacer un montonazo de cosas. 00:19:56
Hay una característica 00:20:03
que es la refactorización, que viene a ser modificar el código 00:20:05
para que tenga un mejor funcionamiento, que esté más ordenado, porque haya que mover unas clases a otras, 00:20:09
porque una variable que está colocada como variable clase la queremos sacar a otra clase. 00:20:17
Todas estas cosas son la refactorización del código, cuyo objetivo es modificar el código manteniendo el funcionamiento, 00:20:22
pero de alguna forma para conseguir una distribución de las variables que igual es más cómoda o está más organizada. 00:20:32
Esto vendría a ser refactorizar. Esto lo trabajáis en la asignatura de entornos de desarrollo, si no recuerdo mal. 00:20:40
Pues todo lo que tiene que ver con refactorización, pues cuelga en Eclipse de esta pestaña y hay algunas cosillas que cuelgan también de Source, 00:20:47
que también tiene que ver con lo que normalmente se habla de la refactorización. 00:20:56
En particular, para poner los getter y los setter, 00:21:01
está aquí en source y nos permite generar los getter y los setter de forma automática. 00:21:04
Y aquí nos dice sobre qué atributos quieres que genere getter y setter. 00:21:10
Vamos a seleccionar los dos, los generamos 00:21:14
y aquí tenemos los dos getter y los dos setter. 00:21:17
como lógicamente 00:21:22
Eclipse no sabe muy bien 00:21:27
qué requisitos nos está pidiendo 00:21:28
el programa, pues hace lo más básico. 00:21:31
Un getter devuelve valor, un setter 00:21:33
aplico al valor 00:21:35
lo que reciba como parámetro. 00:21:36
En nuestro caso 00:21:40
sabemos que, y fijaros, 00:21:41
este sí que tiene 00:21:44
un ámbito, un alcance público. 00:21:45
Desde cualquier sitio del proyecto 00:21:47
podremos acceder a este setter 00:21:48
y este setter nos permitirá 00:21:50
modificar el valor, por mucho que sea privado. ¿Por qué? Porque son métodos propios 00:21:52
de esta misma clase. Entonces el alcance privado nos permite el acceso de estos métodos. 00:21:57
Los setter, como lo que queremos es bloquear que no pueda ser 00:22:03
mayor que cero, pues aquí podríamos decir, sí, y vida 00:22:06
es menor que cero, pero podríamos decir 00:22:11
que y vida es igual a cero. 00:22:19
Ya está. Ya me he garantizado que si aquí 00:22:23
llega un valor negativo, pues lo voy a dejar 00:22:26
al valor cero directamente. Y luego se lo aplico a la variable 00:22:31
de clase. Y aquí pues para la energía podemos hacer la misma jugada. 00:22:36
Dicimos que si la energía es menor de cero, 00:22:47
que valga cero, ahí ya tengo garantías de que no se va a 00:22:50
producir ese valor en negativos. Vamos a ver el enunciado. 00:22:54
Nos dice también sobreescribe el método toString. 00:23:08
Recordad, el método toString es un método disponible dentro de todas las clases y cuando utilizamos una variable de un determinado objeto, de una variable primitiva, en un System.of.println directamente lo que se hace es mostrar en el System.of.println lo que nos devuelva el método toString de esa clase. 00:23:10
fijaros que en un sistema, es algo que hemos comentado más veces, pero en un 00:23:35
System of Println se traga cualquier tipo de objeto, podemos poner 00:23:40
cualquier objeto y siempre nos va a compilar, entonces se utiliza el método 00:23:44
toString para convertir en algo que sea una cadena de caracteres, lo que tenga cualquier 00:23:48
objeto, antes de que concatenando posibles diferentes 00:23:52
informaciones se muestre por pantalla, eso nos está archivando 00:23:56
que todo objeto tendrá el método toString, porque si no, no nos 00:24:00
compilaría, lógicamente. ¿Por qué tenemos el 00:24:04
método toString en todas las clases? Pues porque 00:24:07
siempre hemos dicho que la herencia es única, 00:24:09
cada clase puede tener una sola clase padre, 00:24:13
pero todas ellas, de forma adicional, 00:24:17
y ya se puede decir que quizás no sea tan única 00:24:19
con esta excepción, todas ellas heredan de la clase 00:24:22
object, que está en una jerarquía en árbol 00:24:25
de clases en Java, arriba del todo. 00:24:28
Y esa clase object tiene un método toString, 00:24:31
Entonces, toda clase tendrá por herencia de aquella clase object un método toString disponible. 00:24:34
¿Qué información nos devuelve el toString de la clase object? 00:24:43
Pues como es común ese código para todas las posibles clases, no solo de nuestros programas, sino de todos los programas habidos y por haber, 00:24:47
nos devolverá algo súper genérico y algo que tengan todos los objetos. 00:24:54
En este caso no nos podría devolver un valor de energía o de vida el toStringS porque como es código común no solamente para nuestra clase Pikachu sino para una clase de una pastelería y para otra que hagamos de un instituto y vete tú a saber que no tengan estos otros parámetros, pues no podría decir en aquel código de la clase Object devuelve la energía porque no va a ser común a todos los casos. 00:25:00
entonces lo que devuelve es posición de memoria RAM y el tipo de clase que es 00:25:24
que evidentemente todas las clases, todo objeto pertenecerá a una clase 00:25:30
y todo objeto si se le ha hecho un new tendrá una zona de memoria 00:25:35
como eso en realidad descendiendo a los programas no nos resulta muy útil 00:25:38
es decir un System of Println de algo que sea de un objeto de la clase Pikachu 00:25:44
no va a resultar muy útil en nuestro manejo del programa como usuarios 00:25:50
que nos chive, que ha ocupado la posición de memoria 00:25:55
FA371516, pues lo que podemos hacer es 00:25:57
lo que nos sugiere el programa, sobrescribir el método toString 00:26:02
entonces al sobrescribirlo, lo que van a utilizar los objetos 00:26:06
de la clase Pikachu, en lugar de toString de aquella clase 00:26:10
Object, va a ser la propia que tengamos. 00:26:14
pues venga, pues vamos a ello 00:26:16
nosotros podríamos poner aquí 00:26:20
un public 00:26:23
public to 00:26:24
en lugar de toString vamos a poner toStrand 00:26:26
porque me he equivocado al ponerlo, vale 00:26:29
digo que devuelvo 00:26:31
un string y luego ya 00:26:33
pongo aquí un return 00:26:39
y esto me compila, dice vale 00:26:40
me parece estupendo y yo 00:26:43
tan contento, digo pues ya tengo 00:26:44
sobre escrito el toString cuando incluya 00:26:46
un objeto de la clase Pikachu 00:26:49
en un sistema println me va a poner 00:26:50
lo que yo he puesto aquí 00:26:53
pues hola, me va a decir hola 00:26:54
pero eso no va a pasar, ¿por qué? 00:26:57
pues porque no he sobrescrito el método toString 00:26:59
he puesto toStrand, me he equivocado 00:27:01
al ponerlo, entonces para evitar 00:27:02
estas confusiones, cuando queramos sobrescribir 00:27:05
lo que vamos a hacer va a ser 00:27:07
poner esta 00:27:09
etiqueta con la arroba 00:27:10
que digamos es un metadato, no es 00:27:12
código propio de Java, pero si lo 00:27:15
ponemos, lo que está archivando es que 00:27:17
esto pretende ser un método sobrescrito. Fijaros que en el momento que he incluido 00:27:19
esto, dice, lo siguiente va a ser un método 00:27:23
sobrescrito. Y ahora ya se me queja esto. ¿Por qué? Porque, bueno, como 00:27:27
me he equivocado y he puesto toString aquí en lugar de toString, este método 00:27:31
no existe por herencia desde ningún sitio, ni desde la clase 00:27:35
object, ni desde una posible clase que tuviéramos puesta aquí con un stent. 00:27:39
Como está pasando esto, se me queja el programa. 00:27:43
si no pongo esto, me puede engañar 00:27:45
porque compila, y yo con la idea 00:27:50
de que he puesto aquí toString, feliz de la vida 00:27:53
me puedo ir a otra zona de código, olvidarme de mirar esto 00:27:56
y tener un error por ahí que me lleve un rato 00:27:59
encontrarlo, si pongo el overwrite, ya que la idea 00:28:01
es sobreescribir algo, ya tengo la garantía de que lo que pongo 00:28:05
aquí va a existir en una clase padre, entonces ahora 00:28:08
pongo toString, y ahora ya, fijaros, ya me combila 00:28:11
Y efectivamente algo estaré sobre escribiendo cuando ya no se me queja después de haber puesto el metadato este arroba overwrite. Y el mensaje que queremos que nos devuelva es algo de este tipo. Soy un valor de tipo, pues por aquí, dice que definamos los parámetros tipo, energía y vida. 00:28:16
el tipo no va a tener información del tipo de pikachu que sea si es canto o es el otro 00:28:46
entonces nos falta por definir aquí otro atributo lo ponemos privado también vamos a añadir el 00:28:54
getter y el setter también que lo generamos por aquí pues aquí los tenemos y en el método toString 00:29:17
voy a hacer un copy pega de cómo tiene que ser a no me deja claro una cosa está en el ordenador 00:29:27
de verdad y otra cosa está en la máquina virtual, pues venga, pues lo leemos 00:29:48
soy un, mi nivel 00:29:52
de energía es, la ponemos aquí, soy 00:29:56
un más, un que, pues el tipo 00:30:03
y mi nivel de vida es este otro 00:30:07
bueno, a ver, falta aquí un más 00:30:41
y aquí otro más, bueno, puede utilizar 00:30:47
las variables y energía y vida directamente 00:30:54
a pesar de que son privadas, porque el método toString está integrado 00:30:58
dentro de la misma clase. Si quisiéramos, también podríamos coger y utilizar los métodos 00:31:02
como prefiráis. 00:31:06
En este caso, hay que tener energía. 00:31:10
Bueno, pues otra de las cosas que podemos definir aquí 00:31:25
lo que está claro es que todo 00:31:30
Todo Pikachu, tanto si es Kanto como si es Alola, puede luchar y puede volar y solamente Alola, no perdón, todos pueden luchar y todos pueden entrenar, ¿verdad? Y solamente Alola puede volar, luchar y entrenar. 00:31:34
Entonces lo que podemos hacer es entrenar, ya es obligatorio que lo tengan definido, ya que lo implementa a través del interfaz entrenador y lo que podemos hacer aquí es definir un método, ya que hemos dicho que la clase esta sea abstracta, pues podemos definir un método que sea public abstract, luchar, vale, me dice que quite el identificador de que es abstracto, este método luchar, 00:31:53
¿Por qué? Porque para que tenga métodos abstractos, la clase debe ser abstracta. 00:32:39
En el momento que he definido la clase como abstracta, ya luchar me permite que sea abstracto. 00:32:46
Fijaros, al definir el método este abstracto, no ponemos qué es lo que tiene que pasar al luchar. 00:32:51
Y, en cambio, esto ya implica el hecho de haber definido esta clase abstracta, 00:32:58
ya no podremos definir objetos de la clase Pikachu. 00:33:03
¿Por qué? Porque puede tener algún método, en este caso el de luchar, que no está definido. 00:33:07
No sabría qué hacer un Pikachu para poder luchar. 00:33:13
Y lo que hacemos aquí, esto es algo muy parecido a lo que nos obliga la interfaz. 00:33:19
Cuando una clase sea hija de la clase Pikachu, se verá obligada a implementar el método luchar. 00:33:23
¿Ponemos aquí public AstraVoid volar? Pues no. ¿Por qué? 00:33:35
Porque hacer eso implicaría que todo hijo de Pikachu tendría que desarrollar el método volar y en cambio decimos que solamente va a poder volar a Lola y Kanto, que es un hijo de Pikachu, no puede volar, con lo cual no vamos a poner el volar como un método abstracto en la clase Pikachu. 00:33:39
y bueno y poco más, definición del método de astrazo luchar 00:33:58
nos pide por aquí, pues en la Pikachu yo creo que ya la tenemos más o menos hecha 00:34:09
vamos a hacer alguna de estas clases, la Alola este por ejemplo 00:34:12
bien, la clase Alola hereda Stance 00:34:17
es hija de la clase Pikachu, esto que implica 00:34:32
pues todo objeto de la clase Alola tendrá 00:34:42
estos tres parámetros y tendrá disponible todo esto 00:34:45
tendrá además un método que será 00:34:48
aquel método que estaba definido dentro del interfaz entrenador 00:34:55
que era el método entrenar, y en principio no nos obligaría a desarrollarlo 00:34:59
aquí, ¿por qué? Pues porque tiene un método ya desarrollado aquí, puede utilizar 00:35:03
este, pero no nos compila, ¿por qué no nos compila? Pues 00:35:07
porque en la clase padre hemos definido un método abstracto 00:35:11
que es el método luchar, que no está desarrollado, al ser 00:35:15
hija de Pikachu, obligatoriamente 00:35:19
tengo que desarrollar este método. 00:35:21
A ver, ¿por qué no le gusta esto? 00:35:42
Digo que herede de este. 00:35:45
Ah, vale. 00:35:47
Sí, como he mantenido 00:35:49
este abstracto, pues entonces me dice que la clase 00:35:50
sea abstracta. En este caso ya no queremos 00:35:52
que sea abstracto y ya nos compila. 00:35:54
Podríamos, 00:35:59
con este abstracto que tenemos aquí, 00:36:00
en verdad esta clase podría seguir siendo 00:36:02
abstracta y mantener 00:36:04
sin definir todavía 00:36:11
el luchar. ¿Veis? Ahí me compila. 00:36:13
¿Pero podríamos instanciar un objeto de la clase alola? No, porque no lo tiene 00:36:15
definido. Tendríamos que definir 00:36:19
instanciar de objetos de clases que sean hijas de la clase 00:36:20
alola. Es decir, iríamos, digamos, 00:36:25
en cascada derivando la característica 00:36:28
de la clase y del método. Pero bueno, en nuestro programa 00:36:30
ya, directamente aquí ya implementamos, pues 00:36:33
ahí lo tenemos. Vale, de momento 00:36:37
nos va compilando bien el programa. 00:36:42
A ver qué es lo que tiene que hacer Alola cuando lucha. Dice, cuando lucha, decrementa su nivel de energía en dos unidades. Pues bien, vamos a poner ya lo que tiene que hacer. 00:36:44
recordamos que tiene que alimentar el nivel de energía 00:37:00
la energía la tiene definida aquí como un atributo entero 00:37:05
pero aquí podemos poner ienergía 00:37:08
igual a ienergía menos 2 00:37:13
no, ¿por qué no nos deja hacer esto? 00:37:17
porque lo hemos definido aquí como privado, la energía 00:37:21
entonces tenemos que utilizar los getter y los setter 00:37:24
entonces podríamos poner 00:37:27
un set, set y energía 00:37:29
vamos a hacerlo todo en una línea 00:37:36
y aquí ponemos un get 00:37:39
y energía 00:37:41
menos dos. 00:37:44
Este código que nos hace 00:37:49
recuperar la energía que tiene, le resta 00:37:50
dos y este valor, el que devuelve 00:37:53
esta operación es el que se asigna 00:37:56
al set. Fijaros que 00:37:59
si tuviéramos un nivel de energía de 0, 0 menos 2 00:38:01
pues resultaría ser menos 2 y le aplicaríamos un menos 2 00:38:06
al setter, pero como aquí en el setter hemos dicho que si la energía 00:38:10
es menor que 0, en verdad lo mantenga a 0, pues no nos metería 00:38:14
un valor de energía negativo en ningún caso. Ahora ya me compila 00:38:18
bien, pero el Alola este además 00:38:25
tiene que ser capaz de entrenar. Si lanzamos 00:38:29
el método de entrenar, ¿qué es lo que sucederá? Pues lo que sucederá 00:38:33
será lo que tiene por herencia 00:38:37
desde arriba, que no pone justo lo que queremos que haga 00:38:41
porque no teníamos claro si diferentes 00:38:45
hijos de Pikachu 00:38:48
se comportarían de la misma forma al entrenar. Si no lo hacen 00:38:52
pues lo que vamos a hacer es en cada uno de ellos sobreescribirlo. 00:38:57
entonces ahora aquí cogemos y decimos 00:39:00
sobre escríbeme el método de entrenar 00:39:03
vamos a ver qué es lo que hace Alola para entrenar 00:39:05
Alola por aquí, cuando entrena 00:39:13
incrementa en una unidad su energía 00:39:15
vamos a hacer esto 00:39:18
en este caso lo que hace es incrementar en una unidad la energía 00:39:20
ahí lo tenemos 00:39:27
Alola es capaz de volar 00:39:28
bueno aquí, vamos a hacer el vuela 00:39:35
es capaz de volar y decrementa en una unidad la energía cuando vuela 00:39:38
pues nada, volar es algo particular de Alola 00:39:42
pues será un método que tendrá él y ya está 00:39:47
y lo que hace es decrementar 00:39:49
en una unidad la energía, creo que nos dice 00:39:55
pues ahí lo tenemos 00:39:57
en este caso no ponemos override, ¿por qué? 00:39:58
porque no está sobrescribiendo ningún método 00:40:01
anteriormente definido en clases padres 00:40:03
si lo pusiéramos, ¿qué sucedería? 00:40:06
pues nos diría, oye, volar 00:40:08
mal vas, porque estás intentando sobrescribir 00:40:09
un método volar, pero no existe 00:40:11
por herencia de ningún sitio 00:40:13
no está sobrescribiendo nada 00:40:15
si me lo pones y no lo veráis si te dejo porque bueno pues es un método propio de la clase alola 00:40:16
pues me parece bien en ese caso y luego nos dice por aquí que dispone de un constructor por defecto 00:40:21
casina los valores 5 de energía y vida y reichu alola al tipo bueno esto lo podemos definir de 00:40:29
diferentes formas ponerlo aquí directamente el constructor vamos a hacer diferentes alternativas 00:40:41
ponemos public, acordaros, los constructores 00:40:49
como la clase 00:40:51
pero no devuelve nada 00:40:53
pero no lo indicamos como en el void 00:40:58
entonces lo que 00:41:00
el objetivo es dar a estos 00:41:02
para Lola en particular 00:41:04
un 5 por aquí 00:41:08
un 5 por aquí 00:41:20
y aquí en el tipo 00:41:22
el nombre es 00:41:24
Rachel a Lola 00:41:31
vale, no me está dejando, ¿por qué? 00:41:32
pues porque 00:41:45
porque los tenemos privados estos datos 00:41:46
con lo cual tenemos que utilizar set y vida, 5, set y energía, los getter y los setter, 00:41:49
acordaros que lo habíamos definido privados, si los hubiéramos puesto protective, 00:42:06
pues sí que me dejaría hacer esto directamente, set ese tipo, bueno, pues ahí lo tenemos. 00:42:10
Esta sería una opción, y otra opción que podríamos tener es la siguiente, 00:42:27
Fijaros, podríamos definir aquí en Pikachu, le voy a comentar esta, y en Pikachu podríamos definir un constructor de Pikachu que recibiese un int y vida, un int y energía y un string ese tipo. 00:42:30
Bueno, y aquí se los asignamos, dis y vida, que sea igual a y vida, dis y energía, que sea igual a y energía, una asignación directa, sin más cosa, esto, y dis ese tipo, que sea igual a ese tipo. 00:43:00
Y aquí podríamos tener otro constructor diferente que fuese el siguiente, que recibiese también estos parámetros cuando lo vayamos a crear y ahora desde aquí llamar, me ha dejado de compilar, ahora miramos a ver por qué, bueno aquí podríamos hacer esto, a ver, bueno pues podríamos hacer esta otra jugada, cuando creemos el objeto alola le podríamos pasar al constructor los tres datos y llamar con el método super al constructor que tiene estos tres datos, 00:43:22
tres mismos, esta misma característica, ¿verdad? Con tres datos, 00:44:38
dos enteros y un string, super, pasando los datos. 00:44:42
Entonces, esto lo que hace es ejecutar el constructor de la clase padre, y la clase 00:44:46
padre, fijaros que lo que hemos hecho ha sido, para un constructor con esta misma estructura, 00:44:50
asignarle los valores que recibe como parámetros. Entonces, en este caso 00:44:54
tendría el mismo resultado utilizar este constructor 00:44:58
que este, llamando al super, siempre y cuando, claro, este 00:45:01
este, ¿por qué no me compila ahora? 00:45:05
Bueno, no sé. 00:45:29
No sé muy bien por qué no 00:45:31
deja convivir los dos. 00:45:32
Antes con él solo sí me lo permitía 00:45:35
y ahora que he metido esto otro, ya no. 00:45:36
Ah, bueno, claro. Ya sé por qué no me 00:45:39
deja. No me deja, claro. 00:45:41
Bien. Os explico 00:45:43
el por qué creo que no me deja. Al hacer 00:45:45
esto, 00:45:47
necesita tener un constructor en la clase 00:45:49
padre sin atributos. 00:45:51
Como he creado este, el de por defecto ya no 00:45:53
A ver si cogemos, si decimos un public Pikachu, que existe un constructor sin atributos aquí, ahora ya me compila este también. 00:45:55
Es decir, si tenemos que el hijo tiene un constructor sin atributos, el padre tiene que tener un constructor sin atributos también. 00:46:10
Cuando no existía este, este existía por defecto como siempre, el constructor sin atributos, pero al crear este, este ya deja de estar activo, el de por defecto. 00:46:16
Y como aquí lo teníamos definido sin atributos, necesitaba que el padre también lo tuviera. 00:46:24
Ese era el motivo por el que no me compilaba. 00:46:29
Bueno, tenemos ya os digo dos alternativas. 00:46:32
Una, esta y otra, esta y llamar al atributo al constructor del padre a través del método super. 00:46:34
Vamos a dejar los dos códigos y luego probamos ambos. 00:46:44
dos bueno pues con esto tenemos a pikachu lucha entrena perdona lola lucha vuela entrena y el 00:46:46
constructor el constructor con las dos alternativas luchar entrenar y volar y vamos a hacer el otro el 00:46:57
canto que va a ser prácticamente igual pero sin la capacidad de volar vamos a decirle también que 00:47:04
herede se me queja me dice oye si hereda de pikachu tienes que implementar aquellos métodos 00:47:15
abstractos que tengas definidos en pikachu me pongo aquí me dice añade los métodos no implementados 00:47:29
pues ahí está ya luchar y para no repetir la misma película todo el rato pues vamos a hacer 00:47:35
copia y pega aquí de estas cosas y las modificamos incluso ya que me he traído a luchar por aquí 00:47:43
la clase es canto, pues ahí tengo canto 00:47:53
ahora vemos que, bueno este constructor en sí 00:47:59
no tiene mucho sentido porque canto no va a tener atributos 00:48:04
fijos, pero bueno, ahora lo miramos, aquí este ya no se llama 00:48:08
el constructor alola, pues ya está, por aquí, sí que puede luchar 00:48:14
entrenar, canto no puede volar, vamos a 00:48:18
borrarlo, que viene del copy-paste del otro sitio. Vamos a ver cómo se tiene 00:48:22
que comportar Canto. Cuando lucha, decrementa su nivel 00:48:27
de vida en dos unidades. No sé si antes lo he hecho bien. A ver. 00:48:33
¿Y Alola también decrementaba en dos unidades? Vale. 00:48:41
Alola lo decrementaba en una unidad. Yo creo que había leído aquí antes. 00:48:46
Entonces Alola en una unidad y Canto en dos. Canto 00:48:49
está bien, pero Alola decrementa cuando lucha en una unidad. 00:48:53
y cuando entrena, a ver que es lo que hace cuando entrena 00:48:57
cuando entrena incrementa su energía en una unidad 00:49:05
cuando entrena aumenta su energía en una unidad, entonces si tenemos 00:49:12
solo dos hijos que cuando entrenan aumentan su energía en una unidad 00:49:20
ambos dos, igual no tiene mucho sentido tenerlo en las clases hijas 00:49:24
definidas de entrenar, pues vamos a aprovechar que está en Pikachu 00:49:28
el método entrenar y vamos aquí 00:49:31
a decir que cuando 00:49:35
entrene, Pikachu 00:49:38
aumente su energía en una unidad 00:49:42
y como ya lo aumenta Pikachu 00:49:44
no sobreescribimos el método 00:49:46
en estos dos, vamos a utilizar 00:49:48
el entrenar de la clase 00:49:50
padre para los dos 00:49:52
ya que es igual 00:49:56
esto no lo podemos hacer con 00:49:57
luchar porque cada uno decrementa 00:50:00
en diferentes valores, no podemos 00:50:02
utilizar directamente 00:50:04
la información que tenemos en la clase 00:50:05
padre para luchar, pero para entrenar 00:50:08
a ser común, pues mira, vamos a utilizar esa característica de la programación orientada a objetos 00:50:09
que los dos hereden el método de la clase Pikachu y ya que tiene el mismo comportamiento 00:50:13
hagan lo mismo. Entonces, Kanto ya es capaz de luchar 00:50:18
entrenar, va a ser capaz de entrenar a través de la clase padre 00:50:23
y tenemos aquí el constructor que es capaz de 00:50:27
otorgarle ciertos valores. En el caso de Kanto 00:50:31
dispone de un constructor que recibe como parámetros iniciales 00:50:36
es asignar los valores de energía vida que se recogerán por teclado y el tipo se asigna por 00:50:39
defecto raichu canto entonces éste recibe la energía y la vida y tenemos aquí que le pasa 00:50:46
el raichu canto es vale bueno pues en esta clase no tenemos mucho más que hacer porque ya recibirá 00:50:56
en el constructor estos datos para poder aplicarlos pues vamos a la clase que tiene el 00:51:06
ejecutar pokemon se trata el punto inicio del programa ejecutar pokemon poner el punto inicio 00:51:13
del programa dice que define una referencia a pikachu todavía fijaros no sabemos si va a ser 00:51:49
un del tipo canto o alola con lo cual definimos una referencia a un pikachu pues vamos a hacerlo 00:51:59
podríamos hacer aquí un new pikachu pues no nos deja porque no nos deja crear una instancia un 00:52:07
objeto de pikachu porque porque es una clase abstracta con pose una clase abstracta pues va 00:52:29
a tener algún método al menos que sea abstracto y como no está definido no van a no va a saber qué 00:52:36
hacer y pique que es un objeto de la clase pikachu se supone a la hora de llamar a esto entonces dice 00:52:41
Mira, la referencia te dejo, el new no. El programa lo primero que nos va a pedir va a ser, pues va a decir si es una lola o un canto. Pues venga, vamos a hacer esto. Para pedir por teclado, como siempre, scanner, mi, scan, tendríamos la posibilidad de hacer un buffer reader siempre y cuando trabajemos sobre system in, este es el flujo de datos asociados al teclado. 00:52:49
Y lo que hacemos es ponerle capas como si fuera una cebolla por encima para que nos resulte más fácil su manejo. El manejo más sencillo en realidad desde Java para poder manejar datos leídos desde teclado es con la clase Scanner, disponible en las librerías de Java, pero no es la única. 00:53:21
Está la buffer reader que hablábamos la semana pasada en la tutoría y lo hemos dejado aparcado para el siguiente tema, que al hacer lecturas de ficheros trabajaremos más con esas clases que son las aconsejadas para leer ficheros, pero también nos sirve para leer flujos de datos como por ejemplo los de teclado con Systeming. 00:53:38
de momento vamos a seguir trabajando con Scanner 00:53:57
miScan, pues hacemos un newScanner 00:53:59
y asociamos, fijaros aquí 00:54:03
es donde le asociamos el flujo del datos 00:54:06
es decir, el centro de esa cebolla a la cual le ponemos capas 00:54:09
entonces el flujo de datos sobre el que vamos a trabajar 00:54:13
ahora es el teclado, pues ponemos aquí SystemIn 00:54:16
y le ponemos la capa 00:54:18
de Scanner a través de un objeto miScan 00:54:21
para hacer de forma más cómoda la lectura de los datos 00:54:24
recibidos desde el teclado. Importamos la librería 00:54:27
y ya la tenemos, que está en Java útil. Para hacer el manejo 00:54:30
del programa, fijaros que para System In, como os decía, 00:54:37
solemos meterla dentro de una clase que nos permite manejarlo 00:54:41
más fácilmente, pero en cambio System Out, que es otro flujo de datos, 00:54:45
en este caso comunica nuestro programa con el exterior, y ese exterior 00:54:49
en este caso, la tubería está conectada a la pantalla, la hacemos directamente con 00:54:53
System.out, pues dime el tipo de Pikachu y aquí ponemos a Lola o con un System.out.println, después de mostrar esto me va a llevar a otra línea, pues mira, voy a dejar un System.out.print, otro método disponible dentro del flujo de datos para que me lo deje en la misma línea y así después de la petición, pues puedo escribir con teclado. 00:54:57
Y ahora, pues bueno, pues hago aquí un string sinf de teclado que sea igual a myscan.deskline. Vale, pues aquí cojo la información. 00:55:36
puedo creerme que me va a venir bien o puedo manejar 00:55:58
que la información sea correcta, podríamos poner una condición 00:56:02
con un while por ejemplo, para seguir pidiendo 00:56:06
el dato de si es Pikachu, si es Alola o Canto mientras no se meta 00:56:09
la información que esperamos y podemos decir mientras 00:56:14
ese inf test 00:56:18
sea diferente a, vamos a poner aquí en minúsculas 00:56:21
todo. Vamos a poner que mientras sea igual 00:56:32
a esto o a canto 00:56:44
y ahora cojo y niego todo. Entonces digo 00:56:51
si es igual a este o igual a este 00:56:59
ya me gusta. Si me gusta, uno de los dos será verdadero 00:57:03
perdón, con string no puedo poner igual, tengo que 00:57:09
utilizar métodos. Equals, que me devuelven 00:57:12
true o false. 00:57:17
Uy, qué lío. 00:57:42
A ver. 00:57:44
Ahí está, ¿no? 00:57:46
No. Ahí está. 00:57:48
Entonces aquí nos dice, si es 00:57:58
igual a este, ya me va a valer. 00:58:00
O si es igual a este, también 00:58:03
me va a valer. Cualquiera de los dos. Bueno, ahora 00:58:04
pongo canto ahí a la derecha, que se me ha quedado 00:58:06
una palabra rara. Si es cualquiera 00:58:08
de los dos, todo esto va a ser verdadero. 00:58:10
Si todo esto 00:58:13
es verdadero, con que 00:58:14
cualquiera de los dos sea verdadero, lo unió aquí, 00:58:16
se me convierte el falso y se sale del while. Mientras no sea 00:58:18
alguno de los dos verdaderos, o bien este 00:58:23
o bien este, todo el conjunto 00:58:27
será falso. Entonces si todo el conjunto es falso 00:58:31
y lo doy la vuelta aquí, se convierte en verdadero y me quedo en el while. 00:58:35
Entonces aquí puedo poner un system 00:58:41
.out.println error al meter 00:58:44
el tipo debe ser a lo lado canto. Pongo aquí un print. Bueno, no sé si tendría que meter aquí 00:58:58
un print, un system.out.println porque se me quedará este y este en la misma línea. Luego 00:59:22
lo comprobamos en la primera ejecución. Y tengo que volver a hacer una lectura dentro de las llaves 00:59:27
aquí. Bueno, aquí me quedaré hasta que me diga a lo lado canto. En el momento que esté bien una 00:59:38
de las dos 00:59:47
pues lo que voy a hacer va a ser 00:59:48
hacer la instancia 00:59:50
entonces digo, si 00:59:52
este era un while, pues ahora sí 00:59:54
ese es alola 00:59:58
bueno, el más sencillo es canto, vamos a poner si es canto 01:00:02
pues lo que voy a hacer va a ser 01:00:10
que este, en cuanto al poliformismo 01:00:17
vamos a decir que mi pic, ahora ya 01:00:19
lo instancia un new 01:00:21
y lo defino como canto 01:00:22
si lo hago así, con canto 01:00:25
me estará viniendo por este 01:00:32
constructor, que en realidad no es 01:00:33
el que me interesa. El que me interesa es 01:00:36
este, que es el que está asignando, porque este, fijaros, que no hace nada. Este simplemente está para que 01:00:40
compile. Entonces, aquí le pasaré canto, creo que 01:00:44
recordar que tenía 5, 5 de vida, y luego recibía 01:00:47
como nombre, a ver, canto, como era el nombre, 01:00:51
Raichu Canto. Ah, no, este 01:01:04
es el que se coge por teclado, es el Alola, el que no se 01:01:08
recoge por teclado. Pues entonces vamos a hacer aquí, vamos a poner aquí a Lola 01:01:13
y vamos a decir que a Lola y este 01:01:16
será right to a Lola. Fijaros, este 01:01:23
constructor que recibe los tres parámetros cuando se venga aquí a Lola 01:01:28
será este, este se los pasa a través del 01:01:32
super al constructor padre y el constructor padre 01:01:36
que recibe los tres parámetros se los asigna ya a los atributos 01:01:40
de clase. Bueno, ahí lo tengo construido ya. Y si no, si no es una Alola, pues resulta que va a ser 01:01:44
un canto. Si es un canto, ¿qué necesitamos? Coger el nivel de energía y el nivel de vida. 01:01:56
System of Print, el nivel de vida de Alola. Bueno, va a ser un número. Podríamos hacer un 01:02:08
es int y luego limpiar el buffer cuando toque o bueno podemos si queréis la alternativa a esta 01:02:30
hacemos mi scan igual punto nest line lo cogemos como una línea vamos a definir un momento un int 01:02:42
aunque luego lo quitemos y aus hicimos un y aus igual a integer punto parse int de un string y 01:02:56
string que utilizamos es el que acabamos de coger por teclado y ahora lo que tenemos que hacer es 01:03:08
este es el nivel de vida pues tenemos que hacer para bueno fijaros que si era una lola hacíamos 01:03:25
esto pues si es un canto lo que tenemos que hacer es llamar a canto aquí vamos a poner y aus vida 01:03:35
y aus 01:03:53
energía 01:03:57
y aus vida 01:03:59
y ahora hacemos esta misma 01:04:08
para la energía 01:04:10
de alola 01:04:11
os creo de aquí una variable 01:04:18
entonces aquí tenemos ya la vida, la energía 01:04:21
y ahora creamos canto 01:04:26
con el constructor indicándole 01:04:28
que de vida tiene este nivel 01:04:30
a ver si está en ese orden 01:04:31
vida primero y energía segundo 01:04:34
entonces decimos que de vida 01:04:38
tiene ese valor 01:04:40
y de energía pues tiene este otro. Vale, pues ya tenemos dados de alta 01:04:41
según sea canto o según sea por poliformismo 01:04:49
o según sea una lola, pues tenemos 01:04:54
uno u otro. Hemos utilizado la característica de poliformismo de hacer un 01:04:57
new a un tipo de objeto hijo cuando la referencia en sí por arriba 01:05:06
era una referencia al padre, a Pikachu. 01:05:10
Esta nos pide crear un menú en el que se indique 01:05:23
lo que quieren hacer, si quieren volar, qué cosas quieren hacer. 01:05:27
Vamos a ver si creamos el menú. 01:05:31
Aquí podemos utilizar diferentes estructuras. 01:05:41
Lo primero que vamos a hacer va a ser pedir un dato. 01:05:46
Si vamos a pedir un dato y ponemos aquí un while como estructura de control de repetición, 01:05:48
tendremos que hacer una primera petición del dato aquí fuera. 01:05:52
Si utilizamos un do while, directamente aparecería 01:05:56
do, la primera petición y el while se valora luego aquí abajo. Cualquiera de las estructuras está 01:06:00
bien. Yo la verdad es que estoy más acostumbrado a utilizar el while que el do while, pues voy a 01:06:09
hacerlo de esta forma. Entonces, podríamos crear un método que fuese menú. Bueno, vamos a 01:06:14
poner menú, luego si acaso hacemos el método. Aplicación Pokémon, más podemos poner aquí 01:06:39
instancia vamos a poner o participando 01:07:03
aquí indicamos si participa por ejemplo un raicho 01:07:14
o un canto. Bueno, pues aquí vamos a decir 01:07:29
vamos a poner un barra T, nunca me acuerdo si la barra es esta, si no es esta luego la cambio 01:07:39
a la siguiente para la tabulación y vamos a decir 01:07:44
ponemos aquí 1 volar 01:07:49
no volar es el que es solamente 01:07:54
que está solo disponible en uno de ellos, pues uno luchar 01:07:58
dos, vamos a poner entrenar, bueno el tres, el tres sería 01:08:01
volar o salir directamente, entonces aquí si queréis podemos hacer una distensión ya 01:08:15
de los dos, y coger y poner if, si 01:08:19
mi pic, y para saber 01:08:23
si mi pic durante esta ejecución está trabajando como una lola o como 01:08:29
un canto, podríamos poner instance of 01:08:33
todo junto, instance of de la clase 01:08:37
alola, el instance of 01:08:42
esta comprobación, ponemos la referencia de la clase padre 01:08:46
instance of es una instancia de, es un objeto del tipo alola 01:08:50
si es así devuelve un true o un false, entonces si es una alola 01:08:53
pues ahí podríamos hacer algo, y si no es una alola, como solo tenemos dos alternativas 01:08:57
pues haríamos lo contrario, entonces alola 01:09:02
era el que podía volar o no podía volar? A ver, que me acuerde yo. 01:09:06
Alola es el que vuela y canto 01:09:11
el que no. Pues entonces, si Alola es el que vuela, pues 01:09:14
podríamos poner como un 3 aquí 01:09:18
la opción de volar y 01:09:22
un 4 la opción de salir. Y si 01:09:27
es el que no vuela, pues ponemos aquí como un 3 directamente 01:09:40
la opción de salir, entonces decimos, bueno esto es lo que nos pide, este es el menú que nos saca 01:09:44
y ahora, voy a poner un string S opción, que sea igual a mi scan, aquí ponemos un system.out.println 01:09:58
o print, una nueva línea, dos tabuladores, estoy intentando maquear un poco la salida, vamos a meter 01:10:14
una entrada nueva ahí, los tabuladores 01:10:51
indica tu opción. Y ahora sí que leemos con mi scan 01:10:57
punto next line, aquí 01:11:04
cojo la opción y ahora me quedo aquí 01:11:25
mientras la opción leída 01:11:28
equals 4, ah no, 3, 4 01:11:32
tenemos diferente valor para la opción en este 01:11:43
caso tendríamos que hacer bueno vamos a buscar un truquillo aquí vamos a decir por ejemplo estoy 01:11:47
pensando claro aquí me va a llegar si es uno u otro me va a llegar con el valor 3 o con el 01:12:09
valor 4 no me queda más remedio que hacer aquí un hijo no se me ocurre ninguna forma otra vez 01:12:14
como este utilizo este y por aquí y por aquí seguramente hay alguna forma más limpia de 01:12:26
hacerlo pero bueno defino el string este aquí vale aquí cojo la opción dos veces una por cada 01:12:39
uno de los valores está quedando un poco feo este código ahora para esta opción pero seguramente con 01:13:09
un ratillo más lo dejaríamos más maquillado y claro aquí ahora tendremos que hacer una 01:13:13
comprobación de si esa opción punto equals si es igual en este caso a 4 01:13:20
pues quiere decir que estoy intentando salir se me ocurre podríamos poner aquí esa opción 01:13:31
igual a 10 un valor común y aquí podríamos hacer que si la s opción es igual a 3 la 01:13:38
o que vale a 10. Estoy buscando que esa opción tenga un valor común tanto en un 01:13:53
caso como en otro. Entonces ahora aquí ya puedo decir 01:13:57
que mientras la opción sea diferente a 10 01:14:01
pues que siga. Al final en lo que he hecho en el otro lado ha sido convertir 01:14:05
el valor 3 o 4 para que sea común en 10 en ambos casos. 01:14:10
Entonces si es diferente a 10, fijaros, si hubiera 01:14:16
sido 3 aquí, era para salir, pues sería 10. Acabaría, si hubiese sido 4 01:14:19
aquí, si lo hemos convertido a 10, acabaría también. Si es distinto 01:14:23
a 10, quiere decir que estamos en alguna de las otras. Entonces, aquí 01:14:27
diríamos sí. S opción punto equals 01:14:34
si es igual a 1 de forma común 01:14:39
va a luchar. A 1 va a luchar. Aquí tendremos 01:14:44
que hacer que luche. Else if, si la S opción 01:14:51
es igual a 2, lo que 01:14:58
a hacer va a ser entrenar el solo me queda una opción ya porque si no ha sido salir no 01:15:03
luchar ni es entrenar pues será volar solamente puede hacerlo a lola entonces si queremos luchar 01:15:17
podríamos hacer mi pic punto luchar si es entrenar mi pic punto entrenar y si es volar mi pic punto 01:15:34
volar no me deja. ¿Por qué no me deja volar? Porque volar solamente está disponible 01:16:03
en Alola. Alola 01:16:08
es el que puede volar, pero canto no puede volar. Entonces mi 01:16:11
pig no tiene la posibilidad de volar. ¿Qué podemos hacer aquí? 01:16:16
Pues una vez llegados aquí a este punto, tenemos total seguridad de que 01:16:20
es una Alola. Entonces podemos hacer aquí una Alola, podemos hacer un casting 01:16:24
mi al igual, compórtate 01:16:27
mi pic como pikachu como una lola a lola mi pic 01:16:32
y ahora ponemos aquí y al punto volar y este sí que me deja volar bueno podríamos hacer esta 01:16:40
esto no me ha dado problemas porque pues porque mi pic tiene la en ambos dos tienen la opción de 01:16:50
luchar o de entrenar y una vez hecha esta jugada lo que tendremos que hacer es repetir el menú que 01:16:57
es todo este rollo que hemos puesto aquí todo este rollo aquí está todo esto es el menú verdad 01:17:06
luego podemos si queréis intentar sacarlo a un método común copio este es el del do para aquí 01:17:24
un poco separado y lo pego de nuevo con esto investiga garantizando que después de hacer una 01:17:32
vuelta de éstas vuelve a sacarme el menú y vuelve a hacer la jugada de nuevo fijaros como por aquí 01:17:38
estoy haciendo el next line para coger cada una de las opciones en cada una de las veces 01:17:44
y lo he metido adentro aquí de list y de else para diferenciar el instance of 01:17:47
de Alola o el otro. Igual, después de cada una de las vueltas 01:17:52
estaría bien mostrar cómo vamos de energía y cómo vamos 01:18:00
de vida utilizando el método 01:18:05
que hemos hecho para esto que era el 01:18:09
bueno, llamando al toString, en verdad, era donde habíamos puesto 01:18:12
el nivel de energía y vida, pues entonces con hacer lo siguiente, 01:18:16
aquí poner un system.out.println 01:18:21
barra n, vamos a meter una línea más, más 01:18:26
mi pic. 01:18:36
Este, como ponemos el objeto de la clase, 01:18:40
llamará al println que hemos sobrescrito aquí. 01:18:44
Y bueno, vamos a ver, vamos a lanzar una ejecución a ver qué pasa. 01:18:47
dime el tipo, si ponemos cualquiera se queda ahí en un bucle 01:18:53
vamos a decir Alola, vale, bueno, he puesto aquí Alola 01:19:01
y se me queja y esto es porque 01:19:09
he puesto la A mayúscula creo y estoy comprobando con Alola y canto 01:19:12
todo en minúsculas, entonces lo que tenemos que hacer aquí 01:19:19
al leer, es decir este 01:19:22
igual, vamos a meterlo en minúscula ya que es con lo que estamos 01:19:27
comparando por aquí, ¿verdad? Y aquí hacemos la misma. 01:19:38
También podríamos utilizar aquí el Equals Ignore Case. 01:19:42
Después ejecuto por ahí. Ahora pongo aquí a Lola. 01:19:45
Vale, ella sí que le gusta. Fijaros, la barra 01:19:51
no es la que he puesto. 01:19:53
¿Veis? Barra T, pues es la otra barra. 01:19:56
Ahora lo cambiamos. Entonces vamos a decir luchar. 01:19:59
Dice, soy Rachu, mi nivel de energía es 4 01:20:06
y mi nivel de vida es 5. Es decir, ha restado 1 luchando. 01:20:08
Vamos a luchar de nuevo. Me dice que es 3 01:20:11
y el nivel de vida es 1. Vamos a entrenar y me dice 01:20:14
que el nivel de vida es 4, aumenta en 1, entrenamos de nuevo, nivel de vida 01:20:19
5, nivel de energía 6, va aumentando el nivel de energía de 1 en 1 01:20:23
en Alola. Vamos a bajar 01:20:27
el nivel de energía hasta intentar convertirlo en negativo, fijaros como 01:20:32
no cambia, ya si sigo luchando se mantiene todo el rato el nivel 01:20:35
de energía 0 por la protección que habíamos puesto en el setter. 01:20:39
entrenamos 01:20:43
y empieza 01:20:45
a subir, fijaros 01:20:48
con cada vez que voy dándole a entrenar 01:20:49
en la opción 2, 2, 2, me va aumentando 01:20:52
de uno en uno, y en este caso 01:20:54
que puede volar, pues le doy aquí 01:20:56
a volar, al volar 01:20:58
no recuerdo si era que decrementaba 01:21:02
de uno en uno 01:21:03
al volar, pues bueno, ahí lo sigue haciendo 01:21:05
el nivel de energía decrementando 01:21:08
di a la opción salir 01:21:09
y bueno, y termina el programa 01:21:11
voy a cambiar las barras T 01:21:13
estas que lo he puesto mal en todas partes 01:21:17
y ahora me la muestra 01:21:18
como impreso porque no es la 01:21:20
barra esta del 7 sino que es la 01:21:22
que está en la esquina superior izquierda 01:21:24
del teclado 01:21:26
la que hay que poner por aquí 01:21:27
barra T para que meta ULE 01:21:35
otra barra T por ahí 01:21:37
este barra N también para el otro lado 01:21:49
por aquí volvemos 01:22:00
a tener la misma jugada 01:22:02
ahí está 01:22:04
bien, pues ya cambiadas las barras estas 01:22:11
vamos a hacer otra ejecución 01:22:28
ahora metemos un erróneo, decimos que sea 01:22:29
con combinaciones 01:22:34
de mayúsculas y minúsculas 01:22:36
canto, puesto canta 01:22:38
dime el nivel, vamos a poner 01:22:40
nivel 4 y nivel 3 01:22:46
bueno, ahora queda un poquito 01:22:48
ya pues como pretendíamos 01:22:50
aquí hemos tabulado esto un poquito más 01:22:53
la tabulación del barra T para luchar 01:22:54
entrenar, fijaros como en canto 01:22:56
no nos sale la opción de volar y salir 01:22:58
se nos ha marcado como opción 3, vamos a luchar 01:23:00
y ha decrementado en 2 el nivel de energía, habíamos indicado que fuera 01:23:03
3 y lo ha decrementado en 2, cuanto iba de 2 en 2 al luchar 01:23:08
y ahora el nivel de vida ya es 0, de 1 debe haber pasado 01:23:12
menos 1 pero ya es 0, si entrenamos 01:23:16
empieza a subir el nivel de energía, cada vez que entrenamos volvemos a luchar 01:23:20
y me decrementa y ya está 01:23:25
no tenemos opciones y aquí le damos a la opción 3 pues se nos acaba el programa y bueno poco más 01:23:28
o menos esto era lo que nos pedía el ejercicio no es un poco mejorable ha quedado un poco feo 01:23:39
el código la verdad muy largo por aquí el menú aparece dos veces vamos a poner un método menú 01:23:47
public main en el método menú pretendemos meter no existen opción opción ahora hemos hecho aquí 01:23:51
que lo lea aquí es donde lucha vamos a intentar meter todo esto en el menú entonces aquí tenemos 01:24:41
que llamar a menú ahora nos compila por varios motivos vale entonces el menú aquí no me deja 01:24:54
porque porque no devuelve algo es el primer motivo entonces para que devuelva tenemos que decir esto 01:25:16
que devuelva un string y aquí al final que haga un return de esa opción. Me he pasado, tiene que 01:25:28
estar aquí, este es el final del menú. Publiz, void no, aquí lo tenemos. El siguiente problema que 01:25:49
tengo es que mi pic no lo reconoce por aquí y lo estoy utilizando entonces tendré que pasárselo 01:26:05
como parámetro, entonces pongo aquí pikachu 01:26:10
mi pic 01:26:12
pikachu mi pic, por ahí ya va 01:26:15
compilando, escáner tampoco 01:26:22
lo tengo definido aquí a esta altura, bueno ahora 01:26:24
se lo paso también, escáner 01:26:26
mi scan 01:26:35
entonces aquí en la llamada al menú 01:26:35
voy a pasarle mi pic 01:26:39
que tengo por aquí y el escáner 01:26:44
vale, ahora se me sigue quejando 01:26:46
¿por qué? porque 01:26:50
estoy llamándolo desde un sitio estático al menú 01:26:51
que no lo es, entonces menú 01:26:54
lo voy a definir public static 01:26:56
en realidad no necesito un menú diferente para cada instancia de la clase 01:26:58
ejecutar pokemon y ya parece que compila, otra cosa que no he hecho 01:27:02
por ser puristas es que aquí al final 01:27:09
el while, este es el main, lo que voy a hacer va a ser cerrar 01:27:12
el flujo de datos, mi scan, por ahí 01:27:18
y el método lo he llamado aquí, bien llamado por aquí 01:27:21
pero aquí tengo otra vez toda la jugada del 01:27:26
método, entonces lo voy a volver a llamar aquí 01:27:31
voy a duplicar el nombre de la variable y ahora ya 01:27:33
este bloque de nuevo lo puedo borrar, bueno me queda más limpio 01:27:38
el código del main, fijaros, me queda más limpio 01:27:47
luego tiene otra cosa buena que es que si tenemos que cambiar algo en el menú 01:27:55
un solo cambio aquí ya queda aplicado en los dos sitios que antes 01:27:59
lo teníamos en dos sitios en código y ahora bueno en verdad nos queda probar 01:28:03
a ver si funciona. Alola, bueno, por ahí algo se me ha quedado un poquito feo, como 01:28:07
podéis ver, pero bueno, ahora lo miramos. Entonces, digo 1 para luchar, bueno, parece 01:28:16
que sigue decrementando por aquí el nivel de energía, voy a entrenar, 2, lo vuelvo 01:28:25
a incrementar. Bueno, la otra funcionalidad, solamente hemos modificado la gestión del 01:28:30
menú y parece que sigue funcionando bien. Se dio a 4 para salir, se me acaba el programa. 01:28:35
y luego la gestión está bueno pues seguramente se podrá se podrá hacer de alguna otra forma un 01:28:41
poquito más limpia pero bueno aquí sobre la marcha está la que ha salido para plantearlo y que en el 01:28:48
menú no saliera el valor 3 y el valor 4 para lola y solamente el valor 3 para salir en el caso de 01:28:52
de canto este simbolito vemos por aquí pues fijaros es esto que se me ha colado aquí por 01:29:00
aquí el barra y bueno poco más de esto alguna preguntilla si os ocurre a la hora de resolver 01:29:07
el ejercicio este nada vale pues vamos a ver un momentito el otro el otro de los ejercicios la 01:29:18
otra tarea por lo menos la planteamos si no tenéis ninguna duda de esta y la dejamos hecha hasta 01:29:33
donde sea y así ya el próximo día podemos dejarlo por concluido 01:29:40
esto y pasar a lo siguiente. Esta es otra de excepciones 01:29:44
de otro año, a ver, esta es, menos excepciones. 01:29:51
Bueno, pues nada, aquí lo que pretendemos en la tarea del tema 01:30:04
8 de excepciones es reproducir alguna de las excepciones 01:30:08
más típicas que se nos dan en los programas que si no las tenemos 01:30:12
capturadas pues nos pega un pete y se nos acaba y luego definir 01:30:15
una excepción propia mediante la creación de una clase personalizada un poco lo que estuvimos en 01:30:19
realidad viendo el otro día justo la la tutoría de la semana pasada vuelve a ser un poco volver 01:30:29
a repasar lo mismo vamos a ver a dónde llega hasta dónde llegamos en estos 25 minutos o media hora 01:30:35
que nos queda vamos a crear un nuevo proyecto de java java project excepción bueno por aquí 01:30:41
el enunciado, bueno, pues nos va a pedir una clase donde haya 01:31:19
básicamente necesitamos una clase donde hacer toda la gestión 01:31:23
y luego una segunda clase que sea mi clase excepción 01:31:27
para que herede de excepción y con la que poder trabajar. Y nos pide que 01:31:30
estemos en un menú hasta que se pulse fin. Pues venga, vamos a decir aquí 01:31:35
new class, clase menú. Vamos a poner aquí 01:31:42
que incluya el main ya. 01:31:49
lo he creado justo en la clase 01:31:51
que teníamos de la semana pasada con las excepciones, esta es la nueva excepción 01:32:02
excepciones es la de la teoría de la semana pasada, bueno vamos aquí 01:32:06
clase menú con el main, pues ahí está 01:32:09
como vamos a ir cogiendo por teclado, scanner, mi scan 01:32:19
system.in, indica el tipo de excepción, fijaros 01:32:28
si queremos ponerlo ahí todo en una línea que igual queda 01:33:05
menos claro, pero bueno, podríamos ponerlo así, en una 01:33:09
misma System of Println, barra n, una nueva línea, un tabulador 01:33:13
y podemos poner aquí 01:33:17
aritmética, es por lo que veo en la primera 01:33:20
que teníamos por ahí, podríamos meter otra línea, barra n 01:33:25
ya os digo que igual queda menos claro, pero bueno, por hacer una variante 01:33:29
barra t, ponemos otro tabulador y aquí decimos 01:33:34
puntero nulo 01:33:38
barra n 01:33:40
barra t 01:33:43
formato 01:33:45
barra n 01:33:50
barra t 01:33:53
array 01:33:55
barra n 01:33:57
barra t 01:34:00
y aquí vamos a poner propia 01:34:02
para la clase propia 01:34:03
standout.print 01:34:05
vamos a meter un barra n 01:34:20
barra t, dos barras c, vamos a poner 01:34:28
dos tabuladores, vamos a poner aquí opción 01:34:32
lo que quiere esto, ahí está 01:34:36
y ahora string s opción 01:34:49
y scan punto next line 01:34:53
y ahora para manejar como antes vamos a hacer 01:34:59
un tupper case, un tupper lower case 01:35:11
vamos a hacer en este caso un uppercase y lo convertimos 01:35:16
todo a mayúsculas. Y ahora creamos aquí la estructura 01:35:20
y decimos si ese opción.equals, acordaros 01:35:24
como es un tipo referenciado lo hacemos con equals, no con igual 01:35:28
igual, porque si hacemos un igual igual intentaría 01:35:32
compararnos posiciones de memoria, no contenidos 01:35:36
del string. Entonces si decimos que si es equals 01:35:40
a aritmética, pues tendrá que hacer una cosa, el shift, puntero nulo, formato, perdonad que voy un poco 01:35:44
a toda pastilla con esta, pero esa vez si nos da tiempo a acabarlo, array y propia, bueno pues aquí 01:36:12
tenemos lo que vamos cogiendo en cada caso y aquí podemos hacer, como lo que queremos es capturar 01:36:33
esas excepciones, vamos a poner aquí un try 01:36:38
tabulo ahí 01:36:40
y un catch 01:36:49
vamos a poner una excepción 01:36:51
acordaros la estructura también 01:36:56
en árbol por herencia de las 01:36:59
excepciones, pues estaba excepción 01:37:01
excepción 01:37:02
que estaba en la parte alta 01:37:04
todo el 01:37:07
java class 01:37:10
que estaba en la parte alta 01:37:11
de toda la estructura de excepciones 01:37:20
y luego podríamos ir 01:37:22
mostrando cada una de ellas, capturando cada una de ellas 01:37:23
de forma separada. Vamos a hacer una primera captura en general 01:37:28
y vamos a poner un system of print lnd e 01:37:30
el objeto que se construye cuando se produce la excepción. 01:37:35
Entonces, bueno, pues para hacer, para provocar diferentes 01:37:41
tipos de excepciones, pues para provocar una aritmética 01:37:44
pues serviría con dividir por cero, hacer una división por cero. 01:37:48
Entonces si ponemos aquí intival igual a 10 dividido entre 0, esto no tiene mucho sentido ponerlo por código porque directamente provocamos una excepción, pero esto podría ser una variable construida a partir de un proceso de estar metiendo datos, resta multiplicaciones, lo que dije es el algoritmo, y que casualmente en unas ejecuciones fuese 0 y en otras no. 01:37:51
lógicamente este código así tal cual no tiene no tiene mucha lógica otra de las cosas que veíamos 01:38:13
con las excepciones es que donde en el momento que se producía una excepción el código que 01:38:20
estaba por debajo dejaba de ejecutarse entonces vamos a ponerlo aquí unos mensajes para garantizar 01:38:24
esto de la excepción la excepción se produce aquí con lo cual lo previsible es que esta 01:38:34
otra no se ejecute no suceda ya bueno esto para después lo hacemos metemos un while para hasta 01:38:45
que sea fina vamos a hacer una ejecuciones por separado para que nos dé tiempo a probar bien 01:38:56
las excepciones todo este bloque en realidad dice el enunciado que vaya que se realice hasta que la 01:39:00
opción metida sea fin aquí no lo he puesto en en el menú pero es lo que dice entonces tendríamos 01:39:07
poner un bucle y volver a repetir dentro del while esto, si nos da tiempo lo hacemos 01:39:15
vamos a hacer una ejecución para provocar una excepción 01:39:18
aritmética, por ejemplo división por cero 01:39:23
decimos aritmética 01:39:26
y efectivamente este System.out.println al mostrar 01:39:30
la E, el objeto se ha cargado en la zona de la excepción 01:39:35
con cierta información del contexto que teníamos en ese momento 01:39:39
y al mostrarlo ha llamado al println, en el println ha llamado al toString de este objeto de la clase excepción 01:39:42
que está sobrescrito de la clase object y muestra el tipo de excepción y el motivo por aquí. 01:39:53
Pues ahí lo tenéis. Como decíamos antes, el código venía por aquí, esta línea se ejecuta correctamente, 01:39:59
aquí se produce la excepción y fijaros como el después de la excepción ya no se muestra. 01:40:05
¿Por qué? Porque en este momento de la excepción directamente del try pasa a capturarlo este catch, nos muestra esta información y este código ya no se vuelve a ejecutar nunca más. 01:40:10
Bueno, el puntero nulo, mira, si cogemos y definimos aquí 01:40:20
la otra clase y aprovechamos y definimos la que vamos a utilizar 01:40:26
como clase personalizada luego, vamos a decir mi clase, 01:40:32
ahí lo tenemos, y aquí en mi clase definimos cualquier atributo 01:40:40
o cualquier método, y val, vamos a poner aquí, esta mi clase 01:40:45
tendría un atributo y val en el contexto del enunciado del ejercicio 01:40:50
pues aquí cogemos y definimos, decimos mi clase 01:40:54
mi cla, pero no hacemos el new 01:40:58
pues resulta que eso es un puntero nulo, entonces si ponemos 01:41:03
mi cla punto 01:41:07
puesto mi cal punto y val 01:41:10
igual a cero, bueno se me queja porque es una variable local 01:41:18
no inicializada, como no vamos a hacer el new, lo vamos a poner a nulo. 01:41:24
Entonces esto, efectivamente esto es nulo, pues es el acceso 01:41:29
a un elemento de un puntero nulo, no le va a gustar. 01:41:32
Vamos a poner antes y después de la excepción también. 01:41:38
Ejecutamos. Y ahora nos vamos a ir 01:41:45
por la opción de puntero nulo. Puntero nulo, efectivamente, 01:41:48
pues nada, pasa exactamente igual que antes. Al producirse 01:41:58
el error aquí en este acceso al no haber hecho el new 01:42:02
y ser un puntero nulo, se nos viene aquí la excepción, nos muestra la información 01:42:06
del objeto que se cargó en el contexto de la ejecución 01:42:10
y se muestra el antes de excepción pero no el de después y aquí 01:42:14
tenemos el mensaje. Bueno, de formato, pues de formato 01:42:18
fijaros que por teclado ese val 01:42:26
resulta que ese val vale hola. Ya tenemos un 01:42:30
int y val y entendemos que lo vamos a cargar 01:42:40
desde un string que supuestamente en el contexto de la ejecución 01:42:44
normal tendría aquí un valor numérico 01:42:48
pues hacemos el pase int y le cargamos 01:42:50
para que convierta en un valor de entero y se lo podemos meter en esta variable 01:42:55
la información que tiene ese val como string que supuestamente debería ser 01:42:59
un valor numérico pero resulta que tenemos algo que no es un número 01:43:03
hola en este caso esta operación va a producir va a provocar un error de formato entonces ejecutamos 01:43:08
ponemos por aquí formato pero tenéis number forma de excepción esto nos pasa cuando con 01:43:29
escáner nos ha pasado a veces cuando con escáner hemos metido un dato que estaba mal intentando 01:43:37
carrera hacer un par saint a un valor entero con esta jugada que yo suelo hacer por aquí 01:43:42
bueno, que suelo hacer cuando quiero cargar un entero, no es el caso aquí 01:43:47
bueno, el del array también lo hemos hablado a veces 01:43:53
de hecho hasta ya este tema 01:43:56
nos pegaba en excepción en los programas 01:44:00
si se nos producían y ahora ya sabemos, tenemos capacidad 01:44:02
de poder capturar el error 01:44:05
estabilizar para que el programa tenga sentido 01:44:09
porque a lo mejor se han producido la ejecución 01:44:12
por encima de la excepción haciendo cosas 01:44:15
y para completar con sentido el programa hay que hacer cosas por debajo 01:44:17
que no se realizan, entonces en el catch lo lógico sería 01:44:21
estabilizar el programa para volver a dar sentido a los datos 01:44:24
después de que se hayan ejecutado unos y otros no y tener la posibilidad de 01:44:28
continuar ejecutando en lugar de que nos salga aquí un error de estos 01:44:32
irrecuperables. Pues nada, imaginaos que tenemos aquí un array 01:44:36
int, un array de enteros por ejemplo 01:44:42
y decimos que tengo un tamaño new int 01:44:46
fijaros que esto no es constructor, insisto que ponemos aquí 01:44:53
corchetes en lugar de paréntesis, esto es simplemente una forma de dimensionar 01:44:57
el array, y si ahora decimos aquí miar, lógicamente este 01:45:01
array con dimensión 3, pues las tres posiciones de enteros que tienen es 01:45:06
miar 0, miar 1 y miar 2, si cojo e intento 01:45:10
acceder a la posición 4, pues nada me va a dar un error 01:45:14
me va a provocar una excepción de 01:45:20
array bound de índice fuera de 01:45:24
alcance. Pulsamos por aquí, ponemos aquí array 01:45:28
array index out of bounds excepción. Ahí lo tenemos. 01:45:33
Y bueno, ya nos queda la propia. Para la propia 01:45:39
bueno, pues son situaciones como la que hablábamos en la 01:45:41
tutoría de la semana pasada. Son excepciones que no son 01:45:45
comunes a todos los programas, no es que un array se haya ido de índice 01:45:49
o que hayamos dividido entre cero, sino que son situaciones particulares de nuestro ejercicio. 01:45:54
Entonces, para nuestro contexto de nuestro enunciado, 01:45:59
una situación excepcional la podemos gestionar a través de una clase, en este caso 01:46:02
mi clase la hemos llamado. Fijaros como 01:46:05
cuando se producen las excepciones en líneas generales, deja ejecutarse 01:46:09
el try y se va a una zona de catch. Esta zona de catch 01:46:14
es decir, se lanza una excepción por ese problema 01:46:17
que se ha producido y se captura en el catch. Para que tenga la característica 01:46:21
de poder ser lanzadas, pues tiene que tener cierto código Java 01:46:25
que desconozco cuál es, pero que está muy bien programado en las clases 01:46:29
que tenemos en las librerías de excepciones. Para que mi clase 01:46:33
pueda ser lanzada, necesita esas características. Entonces, o bien las programo yo aquí 01:46:37
el interfaz throughable este 01:46:41
o puedo hacer que herede 01:46:44
lo más fácil, lo más típico 01:46:46
de la clase excepción. 01:46:48
La clase excepción 01:46:50
sí que 01:46:51
puede lanzar excepciones 01:46:54
excepción 01:46:56
sí que puede 01:47:00
lanzar excepciones, entonces si la hago que herede 01:47:02
de esta, mi clase tendrá todas las características 01:47:04
de excepción más lo que yo ponga aquí. 01:47:06
Sin enredarme mucho, porque 01:47:10
no tenemos mucho tiempo, para que 01:47:11
mi clase tenga información 01:47:13
del contexto donde se produce la excepción, ¿cómo puedo 01:47:15
hacérsela llegar? Pues fijaros, para lanzar las excepciones, lo que se hace 01:47:19
es utilizar la instrucción through 01:47:23
de lanzar. En este caso lo que vamos a lanzar 01:47:26
este through que estoy poniendo aquí, en estos casos 01:47:30
se produce de forma implícita, es decir, no lo tengo que poner yo aquí 01:47:36
en el código. Se está produciendo un through que es lanzar la excepción 01:47:40
para que deje el código del trayecto de ejecutarse y se capturen el catch. 01:47:44
Como en el caso particular de mi clase no se da una situación general 01:47:49
que ya esté considerada por Java para que se produzca un lanzamiento, 01:47:55
por código tengo que realizar yo ese lanzamiento. 01:47:58
Entonces, para realizar ese lanzamiento lo que hago es utilizar la instrucción through 01:48:01
y si os fijáis, como comentábamos la semana pasada, 01:48:06
los catch reciben un objeto del contexto en el que se produce 01:48:11
la ejecución, entonces ese objeto hay que crearlo, en este caso 01:48:15
lo lanzamos con el through y es lo que estamos haciendo aquí, estamos creando con el new 01:48:19
un objeto, en este caso de la clase mi clase 01:48:23
y llamo al constructor, fijaros como ya compila 01:48:27
entonces, aquí lanzaría la excepción 01:48:32
lo que hubiese por debajo, como en estos casos de este código 01:48:36
ya no se ejecuta, ¿por qué? porque se ha producido una excepción, fijaros como 01:48:39
directamente no me deja el compilador en este caso meter código ya por debajo porque se da cuenta 01:48:43
que tengo aquí una instrucción through, sería el catch que lo está capturando 01:48:47
y este objeto sería el que estamos lanzando aquí 01:48:53
que sería un objeto de la clase propia 01:48:57
¿qué tendría este objeto de la clase propia? pues en este momento tendría un atributo 01:49:00
int y val y todo aquello que tenga heredado de la clase 01:49:07
excepción. En este contexto, ¿qué es lo que me interesa? Pues conocer cierta 01:49:11
información del momento en el que se produce la excepción para poder 01:49:16
tratarla yo aquí en el catch. ¿Cómo le puede pasar 01:49:21
información? Pues el mejor momento, el sitio donde yo 01:49:25
tengo código en el cual puedo meter cosas en el momento que hago el 01:49:28
through para luego ponerlo aquí disponible, fijaros, es a través de 01:49:32
lanzar el constructor. Entonces aquí estoy lanzando 01:49:36
el constructor, ¿dónde se ejecuta el constructor de mi clase? 01:49:40
Pues aquí. Entonces, imaginaos que lo que me interesa es un IVAL, 01:49:45
el enunciado dice un valor aleatorio o algo de esto, 01:49:50
pues aquí pondría public 01:49:54
mi clase, aquí implemento yo, 01:49:56
IVAL, vamos a poner ale de aleatorio, 01:50:04
y el valor del contexto donde se produce la excepción, que lo recibo 01:50:07
aquí en el constructor, me interesa guardarlo en la clase para que pueda 01:50:12
ser utilizado por otros métodos. ¿Dónde defino los atributos 01:50:16
de la clase? Por aquí. ¿Estos atributos están disponibles 01:50:20
en qué ámbito? En el de la clase. Fijaros la llave. Si yo ahora pongo aquí 01:50:24
más métodos que están dentro de esas llaves, pues estos serán variables 01:50:28
accesibles desde esos métodos. ¿Este método en qué momento 01:50:32
lo estoy llamando? En el momento justo en el que se está produciendo la excepción. 01:50:36
Si tengo aquí cierta información que se la paso por aquí y la guardo en un atributo de clase, lo tendré disponible para manejar esa excepción por aquí. 01:50:39
Si pongo aquí int ival, pues aquí podría decir que ival ale sea igual a ival. 01:50:49
Lo que recibo del contexto de la ejecución en el constructor a través de un parámetro del método constructor me lo guardo en un atributo de clase. 01:51:01
y ahora aquí puedo tener otros métodos pues por ejemplo puedo sobreescribir y le voy a poner 01:51:09
overwrite, así, overwrite, overwrite, overwrite, no me acuerdo cómo se ponía esto, no le voy a poner 01:51:17
overwrite, luego si me acuerdo se lo pongo, public 01:51:43
string, toString 01:51:47
me aseguro de que lo pongo bien, aunque no ponga el overwrite, y ahora 01:51:50
pongo aquí un return, el valor 01:51:56
recibido es, y val, ale 01:52:00
sobreescribimos el método toString de esta forma 01:52:06
tiene que durar un return, y este método sobre screen, el método 01:52:11
tu screen sobre escrito será el que se utilice en el system out println este ya no me compila 01:52:16
porque porque he creado un constructor que recibe un parámetro con lo cual el de por defecto deja 01:52:25
de estar activo y aquí ahora necesitamos un constructor que al que le pasemos un valor 01:52:30
numérico les ponemos aquí un 3 vamos a poner y vamos a hacer una ejecución fijaros que cuando 01:52:38
se produce esta excepción es una captura general de todo esto y lo que estamos haciendo un sistema 01:52:45
println de, recordad este objeto es el que estamos haciendo aquí con el new 01:52:52
y como esto hemos puesto el nombre del objeto, llamará 01:52:56
al toString y el toString está devolviendo 01:53:00
el valor recibido es igual, es atributo de clase que hemos 01:53:04
cargado con la información que hemos recibido en el constructor 01:53:08
no me compila esto por aquí en algún sitio, vale, no me compila 01:53:11
por aquí porque he cambiado el nombre a esta 01:53:22
variable, ya estamos ahí, entonces si pongo aquí propia 01:53:26
pues fijaros, me dice el valor recibido es 3 01:53:35
este 3 lo he puesto aquí a piñón fijo y en el ejercicio 01:53:39
nos decía que hiciéramos un número aleatorio de 01:53:44
entre 0 y 10 me parece que era, bueno pues lo podríamos 01:53:47
hacer o bien con mat o con la clase mat o con la clase random 01:53:51
podemos coger valores aleatorios, bueno esto 01:53:55
echarle un ojillo a la solución que os he dejado resuelta que sería lo que nos faltaría un poco 01:53:59
para completar el ejercicio e insisto que he ido un poco a toda pastilla con este para conseguir 01:54:05
que nos diera tiempo en los 25 minutos que nos quedaban y más o menos ahí estamos. ¿Alguna 01:54:13
dudilla tenéis por ahí? ¿Alguna cosa que queréis consultar o preguntar de este otro ejercicio o del 01:54:21
primero, no, bueno pues 01:54:28
si no tenéis nada 01:54:35
vamos a ir cerrando ya hoy por aquí 01:54:36
ya la semana que viene nos vamos al tema 01:54:39
9, voy parando la grabación 01:54:41
Materias:
Programación
Niveles educativos:
▼ Mostrar / ocultar niveles
  • Formación Profesional
    • Ciclo formativo de grado superior
      • Primer Curso
Autor/es:
JM
Subido por:
Jose Manuel M.
Licencia:
Dominio público
Visualizaciones:
27
Fecha:
17 de marzo de 2025 - 19:30
Visibilidad:
Clave
Centro:
IES ALONSO DE AVELLANEDA
Duración:
1h′ 54′ 49″
Relación de aspecto:
1.78:1
Resolución:
1920x1080 píxeles
Tamaño:
262.41 MBytes

Del mismo autor…

Ver más del mismo autor


EducaMadrid, Plataforma Educativa de la Comunidad de Madrid

Plataforma Educativa EducaMadrid