2025-03-17-Programacion - Contenido educativo
Ajuste de pantallaEl ajuste de pantalla se aprecia al ver el vídeo en pantalla completa. Elige la presentación que más te guste:
Tareas de los temas 7 y 8
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
de
01:37:07
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