Clase 22-04-2024 - 1 - 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:
Vale, pues nuestra arquitectura de clases
00:00:00
Aplicación que tiene una interfaz gráfica
00:00:03
Repito, la interfaz gráfica lo único que aporta es
00:00:07
Que mi forma de introducir datos
00:00:10
Y mi manera de ver los resultados
00:00:12
Va a ser distinta al escáner y al System Outprint LN
00:00:15
Todo lo demás es igual
00:00:20
Si nosotros tenemos que trabajar con alumnos
00:00:22
Con profesores, con clientes, con facturas
00:00:25
Esas clases seguirán estando y seguiremos teniendo nuestras colecciones de facturas de clientes que tendremos que recorrer, con las que tendremos que hacer cosas, con las que tendremos que hacer sumas. Todo eso seguirá estando. Lo único que cambiará es la forma en la que nosotros introduzcamos los datos desde fuera y la manera en la que veremos los resultados. Pues la suma del total de facturas, la nota de un alumno, es lo único que va a cambiar.
00:00:28
¿Vale? Es lo único que va a cambiar
00:00:52
Bueno, pues entonces
00:00:54
Una aplicación que tiene una interfaz gráfica
00:00:56
Que hemos decidido que tiene una interfaz gráfica
00:00:59
Tendrá entonces
00:01:01
Como elemento para
00:01:02
Recoger datos y mostrar resultados
00:01:04
Un JFrame
00:01:07
Que es lo que vimos el otro día
00:01:08
Pero un JFrame básico
00:01:10
Normal y corriente, no hombre, no
00:01:13
Uno personalizado
00:01:14
Uno personalizado
00:01:16
Al aspecto que nosotros queremos
00:01:19
Entonces, personalizar un JFrame básico es hacer una clase nuestra que hereda de él, ¿vale? Que hereda de él. Bueno, pues entonces, la arquitectura, la arquitectura básica, una de ellas, vamos, para mostrar una aplicación en swing es, me voy a hacer mi JFrame personalizado, es decir, heredero de JFrame.
00:01:21
Y ahora, este JFrame cuando se construye, este JFrame se construye cuando arranca la aplicación, obviamente, en mi main, aquí se construye, cuando arranca la aplicación en el main se construye aquí, ¿no? Aquí, pues aquí es lo que estoy haciendo, construirlo cuando arranca la aplicación, luego además le doy un tamaño, el que yo quiera, y lo hago visible para que se vea, ¿vale?
00:01:44
Y podría hacer más cosas con él porque V, por ser JFrame, tiene un montón de métodos para hacer cosas que uno se puede poner a investigar
00:02:10
y trabajar con Swim al nivel de profundidad que le dé la gana.
00:02:19
Vale, pues entonces, pero se construye aquí en el constructor.
00:02:24
Por eso decíamos, vale, pues en el constructor, que es este, en el constructor, es donde yo tengo que poner todo el rollo,
00:02:28
Todo el rollo patatero de
00:02:34
¿Qué componentes quiero?
00:02:36
Añadírselos a algún panel del frame
00:02:40
¿Vale?
00:02:42
Porque recordad que los componentes
00:02:44
Que son los que reciben y muestran datos
00:02:46
Botones, áreas de texto
00:02:48
Los componentes
00:02:50
No van directamente al frame
00:02:52
El frame es como el marco raíz
00:02:55
Al frame van paneles
00:02:57
Y los paneles ya llevan los componentes
00:02:59
¿Vale?
00:03:01
Pues entonces, nosotros decidimos qué componentes me interesan en este ejemplo
00:03:02
Queríamos una etiqueta
00:03:07
Simplemente para mostrar el texto e introduzca el año
00:03:10
Un área de texto
00:03:13
Para poder introducir yo el dato
00:03:15
Una etiqueta para mostrar el resultado
00:03:19
Y un botoncito para decir, calcula a ver si es bisiesto
00:03:21
Una vez decidido lo añadíamos a un panel
00:03:25
¿A cuál? Podría hacerle un panel si me daba la gana
00:03:27
un jPanel
00:03:30
pero podemos trabajar con el que ya me da el frame
00:03:31
que me da uno por defecto
00:03:36
que yo lo puedo sacar con este método
00:03:37
con este método
00:03:39
podíamos sacar el panel por defecto
00:03:41
del frame
00:03:43
y a ese panel por defecto le añadimos los componentes
00:03:45
si añadimos los componentes y más
00:03:48
¿qué ocurría? que se ponían unos
00:03:51
encima de otros, no íbamos a ver ninguno
00:03:53
nada más que el último
00:03:55
entonces a ese panel hay que darle
00:03:56
un gestor de ubicación
00:03:59
que él use
00:04:01
para decidir
00:04:04
donde van los componentes, gestores de ubicaciones
00:04:05
miles, para hacer gestión de ubicación
00:04:07
hay mil clases, mil rollos, mil historias
00:04:09
que uno no pasa nada, se coge un libro
00:04:11
se lee las 500 primeras páginas
00:04:13
y con esas 500 primeras páginas, pues ya conoce
00:04:15
todos los gestores de ubicación
00:04:17
como nosotros no nos vamos a meter por ese camino
00:04:18
pues por ejemplo
00:04:21
vamos a fijar un gestor
00:04:23
de ubicación que era este
00:04:25
el de tipo flow layout, este
00:04:27
lo instancio y le digo al panel
00:04:29
oye, que este es tu jefe, este es tu gestor
00:04:32
de ubicación y a partir
00:04:34
de ahí ya los componentes
00:04:36
se van colocando como el jefe
00:04:38
flow layout manda
00:04:40
y el jefe flow layout como manda
00:04:41
pues manda uno detrás de otro
00:04:43
¿vale?
00:04:45
entonces en cuanto a la construcción del aspecto
00:04:48
de la vista, eso es lo más sencillo
00:04:50
ahora la vista se tiene que comportar
00:04:52
cuando yo haga algo
00:04:54
tienen que pasar cosas
00:04:56
entonces hay que decidir
00:04:57
qué tipo de acciones
00:04:59
sobre la interfaz, qué tipo de acciones
00:05:01
me interesan a mí
00:05:04
capturar, qué tipo de acciones
00:05:05
en nuestra aplicación
00:05:07
la única acción que nos
00:05:09
interesaba
00:05:12
capturar
00:05:16
era la de darle al botón
00:05:17
era la única acción que nos interesaba calcular
00:05:22
luego entonces, la arquitectura
00:05:24
¿cuál era? pues la arquitectura
00:05:26
era, para capturar
00:05:28
un evento
00:05:30
para capturar un evento y darle al botón es un evento
00:05:31
estirar una ventana es un evento
00:05:34
que el ratón navegue es otro evento
00:05:36
pues para capturar un evento
00:05:40
tenemos que hacer una clase
00:05:43
que sea capaz de permanecer a la escucha de ese evento
00:05:45
y dentro de esa clase
00:05:49
metemos el código de respuesta al evento
00:05:52
entonces una clase que sea capaz de permanecer
00:05:54
la escucha de un evento no es una clase
00:05:58
cualquiera, tiene que ser una clase
00:06:00
con ese comportamiento
00:06:02
comportamiento, ser capaz de escuchar
00:06:03
a ver si pasa esto
00:06:06
ser capaz de estar atento, eso no es una
00:06:08
clase cualquiera que se pueda programar
00:06:10
así como así, porque implica programar
00:06:12
muchas cosas raras, implica programar
00:06:14
estar yo pendiente del ratón, ¿de cómo programamos eso?
00:06:16
no sabemos programar eso
00:06:19
pero afortunadamente hay una
00:06:20
interfaz ya hecha que es Action Listener
00:06:22
que tiene todo eso hecho
00:06:25
estupendo, me hago yo una clase que implemente esa interfaz
00:06:26
¿vale? que es lo que hicimos aquí
00:06:30
me hago yo una clase que implemente esa interfaz
00:06:39
magnífico, ya tengo una clase que es capaz de estar pendiente
00:06:42
de escuchar los eventos que ocurran sobre la interfaz
00:06:46
bueno, y ahora ya, dentro de esa clase
00:06:50
la parte de programar, ser capaz de estar pendiente, no tengo que hacerla
00:06:54
esa ya la coge de lo que esté por defecto
00:06:58
hecho en Action Listener, ya lo coge de ahí
00:07:01
yo solo tengo que añadir
00:07:02
el que, solo tenemos que añadir
00:07:04
el código de respuesta
00:07:06
a el evento
00:07:08
escuchar el evento ya lo hace ella sola
00:07:09
por ser Action Listener, ya lo hace sola, estará ahí pendiente
00:07:12
solo tenemos que ponerle
00:07:15
y cómo vas a responder
00:07:16
cuando ese evento ocurra, cómo vas a responder
00:07:18
porque cada aplicación
00:07:20
querrá responder de su manera
00:07:22
bueno, pues ese cómo vas a responder
00:07:24
esa respuesta lo metíamos en este método que había que sobreescribir obligatoriamente
00:07:27
este método. Entonces en nuestro caso nuestra respuesta era
00:07:31
coger el año que habíamos metido, si es bisiesto
00:07:34
poner el texto en la etiqueta y si no lo es poner este otro texto
00:07:38
en la etiqueta. Entonces para hacer el código de
00:07:42
respuesta necesitábamos el text fill
00:07:47
de la ventana, esta, este de aquí y también
00:07:50
necesitábamos
00:07:59
la etiqueta
00:08:00
esto de aquí
00:08:02
esta, como eran variables
00:08:04
locales al main teníamos un problema
00:08:09
pero nosotros
00:08:10
sabemos resolver eso pasando
00:08:13
por parámetro lo que un método necesite
00:08:15
¿vale?
00:08:17
entonces esta clase necesita
00:08:18
estas propiedades ¿vale? se las paso
00:08:21
al constructor por parámetro
00:08:23
se las paso por parámetro
00:08:24
aquí las tengo pasadas por parámetro
00:08:26
las uso para inicializar
00:08:28
variables de esta clase
00:08:30
ahora ya las que pase por parámetros
00:08:32
son estas, las mismas
00:08:34
porque las he inicializado
00:08:36
y ya está, y ya las tengo
00:08:38
y ya puedo trabajar con ellas, etc.
00:08:40
¿vale?
00:08:44
bueno, pues esto es lo que se supone
00:08:47
que tenía que estar claro a día de hoy
00:08:48
y cualquier
00:08:50
y la que os dije de hacer la suma
00:08:51
la resta era hacer esto mismo
00:08:54
pero cambiando el código de respuesta
00:08:55
nada más, y cambiando la vista
00:08:57
bueno, pues
00:08:59
el que no lo haya hecho que lo haga
00:09:01
porque es repetir esto de aquí
00:09:04
vale, pues a ver
00:09:05
seguimos avanzando un poco
00:09:09
bueno, pues en este caso
00:09:12
el código de respuesta
00:09:23
para mi
00:09:26
ah bueno, y se me ha olvidado decir
00:09:28
que esta clase, ActionListener
00:09:30
que es una clase que es capaz de escuchar
00:09:32
y además ofrece un código de respuesta
00:09:34
esta clase
00:09:37
el objeto
00:09:38
que instanciemos hay que decirle a qué componente
00:09:40
tiene que escuchar, claro, porque
00:09:42
si no, ¿qué evento
00:09:44
escuchamos? ¿El que haces en el ratón? ¿El que haces
00:09:46
en la área de texto? ¿Cuál? ¿A cuál escuchas?
00:09:48
Hay que decirle, oye tú,
00:09:50
objeto de esta clase
00:09:52
de quien tienes que estar pendiente es de este.
00:09:53
¿Vale?
00:09:56
Luego los objetos que se instancian de estas
00:09:58
clases, esos objetos
00:10:00
van a estar pendientes
00:10:02
de los componentes que nosotros le digamos.
00:10:04
pero hay que decirles de qué
00:10:06
componentes tiene que estar pendiente
00:10:09
si no decimos de qué
00:10:11
componentes tiene que estar pendiente, no va a estar pendiente de nadie
00:10:13
eso como lo hacíamos
00:10:15
pues decíamos, oye tú, botón
00:10:17
botón
00:10:19
como el componente, como esa clase
00:10:21
escuchadora, esa clase capturadora
00:10:23
tiene que estar pendiente del botón
00:10:25
porque el evento
00:10:27
que nos interesa es este
00:10:29
del botón
00:10:31
¿vale?
00:10:32
Como el objeto de la clase capturadora
00:10:34
Tiene que estar pendiente de este
00:10:38
Pues hay que decirle
00:10:40
Oye tú, botón
00:10:44
Va a estar pendiente de ti
00:10:46
Y eso se le decía mediante el método
00:10:49
AddActionListener
00:10:50
Va a estar pendiente de ti
00:10:52
Un objeto de esta clase
00:10:53
¿Vale?
00:10:55
Que instanciábamos aquí
00:10:56
Pasándole los datos que necesitábamos, etc.
00:10:57
Si esto no lo hacemos
00:11:00
Porque se nos olvida
00:11:02
Pues entonces ya podemos tener clase
00:11:03
Escuchadora
00:11:06
Podemos tener lo que nos dé la gana
00:11:07
Ahí he cerrado la esta
00:11:09
Pero no he
00:11:14
Ahí está la consola
00:11:15
Aquí
00:11:21
Ahí, vale
00:11:22
Vale, si a mí se me olvida esto
00:11:26
Ejecuto
00:11:31
Y ahora ya puedo darle al botón
00:11:32
Todo lo que me dé la gana
00:11:34
Que esto no hace nada
00:11:35
¿Por qué? Porque el botón no tiene asociado
00:11:36
un objeto de la clase
00:11:40
capturadora, no va a hacer nada
00:11:42
pero no lo tiene asociado
00:11:44
entonces tendríamos que
00:11:45
cuando hagamos esto
00:11:53
ahora ya si, este botón tiene asociado
00:11:55
un objeto de esa clase
00:11:58
luego ahora ya si, cuando yo
00:11:59
ejecute esto, pues ahora ya si
00:12:01
tendrá respuesta, vale
00:12:05
vale, bueno, alguna duda
00:12:07
no, verdad
00:12:17
bueno, pues todo es práctica
00:12:17
todo es práctica, volver a hacerlo
00:12:24
volver a hacer lo mismo de clase
00:12:26
y luego volver a hacerlo cambiando una cosita
00:12:29
que a mí se me ocurra, pues en lugar de que muestre
00:12:31
si es bisiesto, que muestre no sé qué
00:12:33
pues ahora que me muestre dos cosas
00:12:34
cambiando cositas, esa es la única manera
00:12:36
¿vale? práctica
00:12:38
vale, pues a ver
00:12:39
seguimos
00:12:42
aquí en este caso
00:12:43
el código de respuesta
00:12:46
al hecho de
00:12:49
pulsar al botón
00:12:51
pues bueno, era cortito
00:12:52
Era tocar solamente
00:12:53
Un text field para sacar el dato
00:12:56
Y tocar una etiqueta
00:12:59
Para poner ahí el resultado
00:13:01
Era un código cortito
00:13:03
Y solo necesitaba dos cosas
00:13:05
De la interfaz, dato y result
00:13:07
Solo necesitaba eso
00:13:08
Entonces el hecho de que no pudiera acceder
00:13:09
A ellas, el hecho de que no pudiera acceder
00:13:12
Lo hemos solucionado
00:13:14
Relativamente fácil diciendo
00:13:15
Bueno, pasaselo al constructor
00:13:18
Vale, pasaselo al constructor
00:13:19
inicializas esto, con esos datos
00:13:22
que has pasado ya puedes trabajar con ellos
00:13:25
pero hombre, es un poco engorroso
00:13:26
es un poco engorroso
00:13:29
porque si
00:13:31
el código de respuesta, el evento
00:13:32
tuviera que tocar un montón
00:13:35
de cosas de la interfaz, un montón
00:13:37
te podría ocurrir un montón
00:13:39
y poner un desplegable nuevo y añadir
00:13:40
un slider, vete a saber, igual el código de respuesta
00:13:43
de un botón es hacer un montón de cosas
00:13:45
y tiene que tocar un montón de
00:13:47
componentes de
00:13:49
la clase frame
00:13:51
pues esta solución es un rollo, porque tenemos que hacer
00:13:52
un constructor al que le pasemos ahí un montón
00:13:55
de cosas, no es la solución
00:13:57
habitual, que normalmente uno
00:13:59
uno utiliza
00:14:01
o uno ve, no es la solución habitual
00:14:03
¿vale?
00:14:04
entonces, ¿cuál es
00:14:07
la estructura más cómoda?
00:14:09
para que desde aquí
00:14:11
desde esta clase capturadora
00:14:13
podamos acceder
00:14:15
a todo lo que hay en el frame
00:14:17
¿Qué será nuestro problema, verdad?
00:14:18
Desde aquí acceder a todo lo que hay en el frame
00:14:22
¿Cuál es la forma más sencilla?
00:14:25
Bueno, pues la forma más sencilla es
00:14:28
incorporando una nueva estructura de clases
00:14:30
que se usa bastante por las ventajas que ahora podemos ver
00:14:35
que es la estructura de clases internas
00:14:39
¿Vale?
00:14:42
Clases internas, lo hemos imaginado hasta ahora, ¿verdad?
00:14:44
es una de las cosas que dice
00:14:46
cuando yo os digo una clase puede tener dentro
00:14:49
propiedades y métodos
00:14:51
y luego siempre a veces decía, bueno os miento un pelín
00:14:53
pero os tengo que mentir porque bueno
00:14:55
aparte de propiedades y métodos puede tener otra clase
00:14:57
¿vale?
00:14:59
y entonces el hecho de que
00:15:02
una clase pueda tener otra
00:15:03
dentro y ahora veremos lo que significa eso
00:15:05
nos facilita el diseño un montón
00:15:07
en un montón de situaciones
00:15:09
en una de ellas cuando
00:15:11
trabajamos con interfaces gráficas, es básico
00:15:13
Es básico, ¿vale? El poder hacer una clase dentro de otra
00:15:15
Vamos a
00:15:18
A entender un poco eso de las clases internas
00:15:19
Porque se usa muchísimo
00:15:25
En un montón de contextos
00:15:26
No solo en interfaces gráficas
00:15:28
Vamos a intentar entenderlo
00:15:30
Vale
00:15:34
A ver
00:15:37
Esto si alguien lo ve ya se habrá dado cuenta
00:15:39
De que se ve en espejo
00:15:44
Pero es que no sé cambiarlo
00:15:45
Y da igual, tampoco
00:15:48
Se entiende de igual
00:15:50
Quien quiera entenderlo va a entender igual
00:15:51
A ver
00:15:53
Pues venga, clases
00:16:07
Vamos a ver un poquito
00:16:11
Sin volvernos locos tampoco
00:16:12
Vale, pues a ver
00:16:14
Nosotros cuando hemos hecho una clase
00:16:41
Hasta ahora
00:16:43
Porque hemos tenido que definir una clase
00:16:44
Silencio
00:16:47
Una clase cliente, una clase factura
00:16:50
Una clase producto, porque nuestra aplicación
00:16:53
Trabajaba con eso
00:16:55
¿Vale? Pues
00:16:56
Imaginaos la clase A
00:16:59
¿Vale? Nuestra clase
00:17:04
¿Qué tenía? Tenía siempre
00:17:07
Propiedades que son
00:17:09
Las que van a caracterizar
00:17:11
Los objetos de esa clase
00:17:14
¿No? La clase factura
00:17:15
Pues puede tener, ¿Qué caracteriza una factura?
00:17:18
Su número, su concepto
00:17:20
¿Qué caracteriza a un cliente?
00:17:21
Su NIF, su nombre, bueno las propiedades
00:17:23
Lo de toda la vida, ¿no?
00:17:26
¿Sí?
00:17:28
lo que fuera, además una clase que tenía los métodos
00:17:30
que es los objetos de esa clase a qué código pueden invocar
00:17:37
normalmente ese código para hacer cosas con los datos de ese objeto
00:17:41
con parámetros que ese objeto recibe y hacer ahí funcionalidades
00:17:45
pues una factura puede llamar a métodos para hacer funcionalidades
00:17:49
relacionadas con calcular el importe con IVA, lo que sea
00:17:53
¿vale? entonces dentro de esos métodos el constructor, claro, etc.
00:17:56
eso era la otra cosa que tenía una clase
00:18:00
los métodos, es decir
00:18:05
¿qué funciona? ya el código de la aplicación
00:18:07
¿qué quiero yo
00:18:09
que haga esa aplicación?
00:18:11
esa aplicación lo que va a hacer lo metemos en métodos
00:18:12
que son los que hacen las cosas
00:18:15
pues obtener el resultado de no sé qué
00:18:16
calcular la edad
00:18:19
del cliente, lo que fuera, lo que yo quiero
00:18:21
que haga la aplicación va a ir en los métodos
00:18:23
correspondientes que trabajan con las propiedades
00:18:25
de la clase
00:18:27
para que cada objeto pueda
00:18:28
llamar al método, trabajando con sus propias propiedades
00:18:31
etcétera, lo de siempre, vale
00:18:33
bueno, pues una clase
00:18:35
además de todo esto
00:18:37
propiedades y métodos puede tener también
00:18:39
dentro, lo pongo ahí para que no me
00:18:41
cabe, una o más clases dentro
00:18:45
de ella, una o más clases
00:18:47
directamente tal cual, imaginaos que esta
00:18:48
tiene además dentro
00:18:51
otra clase
00:18:53
de nuevo con sus propiedades
00:18:54
y sus métodos, me da lo mismo
00:19:00
vale, pues a ver que implicaciones
00:19:02
tiene que una clase esté dentro de otra.
00:19:16
A ver, tenemos que verlo de alguna manera
00:19:20
como de esta clase se instanciarán objetos
00:19:22
y de esta otra se instanciarán otros
00:19:25
que son distintos, ¿vale?
00:19:27
No es que el hecho de que esta clase esté dentro
00:19:31
signifique que cuando yo hago un objeto de esta clase
00:19:35
va a tener dentro un objeto de esta otra, no.
00:19:40
Para que esta clase, cuando yo instancie un objeto de esta
00:19:43
tenga dentro un objeto de esta otra
00:19:46
pues tendría que hacer una propiedad así
00:19:48
¿no?
00:19:50
entonces si yo le hago una propiedad
00:19:53
así, esta clase
00:19:54
tiene dentro cuando yo la instancie
00:19:56
además de un entero A y un entero B
00:19:58
tiene dentro un objeto de esta otra
00:20:00
entonces cuando yo quiero que una clase
00:20:02
un objeto de una clase tenga dentro
00:20:04
un objeto de otra
00:20:06
esto no es un rollo de clases internas
00:20:07
yo lo he hecho siempre así
00:20:10
declaramos una propiedad
00:20:11
cuyo tipo sea esa otra clase y ya está
00:20:13
Y esa es la relación de composición de toda la vida.
00:20:16
Un cliente puede tener dentro un objeto pedido, por ejemplo.
00:20:19
Pues el cliente tiene su objeto pedido dentro.
00:20:26
Y cuando instancie un cliente, ese cliente tendrá dentro un objeto pedido
00:20:28
que también habrá que instanciar, lo que hemos trabajado siempre.
00:20:33
Bueno, pues lo de las clases internas no es eso.
00:20:36
No es que un objeto de la clase A tenga obligatoriamente un objeto de la clase B.
00:20:39
No, estos se instancian por separado.
00:20:43
El que sea una clase interna, la implicación que tiene es conceptual, en realidad, es conceptual y es, oye, yo puedo instanciar objetos de A cuando me den la gana y no necesito saber nada de la clase interna B, nada, puedo instanciar objetos de A cuando yo quiera, ¿vale?
00:20:46
Por ejemplo, puedo instanciar un objeto de la clase A como lo instancio de toda la vida.
00:21:05
Y ya está.
00:21:17
Y este objeto, a este objeto B no le interesa nada.
00:21:18
No le interesa para nada a este objeto.
00:21:23
Ni es consciente de su existencia, ni tiene ningún objeto B dentro, nada.
00:21:26
Vale, pero ¿ahora qué pasa con B cuando yo quiero instanciar objetos de la clase B?
00:21:32
Bueno, pues esto es un tema conceptual.
00:21:37
estos objetos se supone que son objetos
00:21:38
que por diseño de la aplicación
00:21:42
solo tiene sentido que existan
00:21:43
si existe un objeto de la clase A
00:21:45
previo, si existe un objeto
00:21:48
¿vale? por ejemplo
00:21:50
imaginaos que hay una aplicación en la que
00:21:52
hay
00:21:54
pues clientes
00:21:55
¿vale? y hay pedidos
00:22:04
y yo quiero
00:22:06
y solo tiene sentido que exista un pedido
00:22:08
si existe un cliente
00:22:10
Solo tiene sentido que está un pedido si existe un cliente.
00:22:12
Entonces, yo podré instanciar un pedido si existe un cliente previamente,
00:22:15
pero eso no significa que mi cliente tenga dentro ese pedido.
00:22:19
No lo tiene dentro.
00:22:22
Es otra forma de relacionarse.
00:22:24
Yo puedo instanciar mi cliente, no tiene ningún pedido dentro.
00:22:26
Y luego, para instanciar la clase pedido que está dentro,
00:22:29
para instanciarla, la tengo que instanciar si existe un cliente previamente.
00:22:32
Y entonces, la primera implicación que ocurre es
00:22:38
Que esta clase no se llama así.
00:22:40
Esta clase, su nombre, por ser clase interna esta,
00:22:43
su nombre es más complejo, es esta.
00:22:47
Esta clase no se llama así.
00:22:50
Y siguiente implicación.
00:22:55
Que para instanciarlo, hay que instanciarlo asociado
00:22:57
a un objeto de la clase A previo.
00:23:01
Algo así.
00:23:03
Ahora lo hacemos en...
00:23:05
¿Vale?
00:23:13
Entonces, esta es la idea.
00:23:17
Los objetos de la clase A se instancian y no...
00:23:18
Para ello, si es transparente, los objetos de la clase B, ¿vale?
00:23:21
Es completamente transparente.
00:23:26
No es como cuando tienes una clase cliente con un objeto pedido dentro.
00:23:27
Para instanciar el cliente tienes que instanciar el pedido.
00:23:31
Aquí no.
00:23:33
La clase es interna.
00:23:35
Tú puedes instanciar objetos de esta clase y para ella esta otra clase es que ni existe, ni le interesa, ni le importa.
00:23:37
Pero ahora sí, cuando instancias objetos de esta, por ser interna esta otra, primero el nombre cambia.
00:23:43
El nombre de la clase realmente cambia, se convierte en este.
00:23:50
Y segundo, solo puedes instanciarlos asociados a un objeto que ya exista
00:23:53
de la clase en la cual está contenido.
00:23:58
Entonces, no es que sea una arquitectura que sea imprescindible,
00:24:02
tú puedes hacer clase A y clase B por libre, pero te facilita dos cosas.
00:24:07
La primera es un tema de diseño.
00:24:12
Con esto fuerzas a que solo puedan existir ya por código directamente
00:24:15
objetos de este tipo, si previamente
00:24:19
existen de este, que eso puede tener
00:24:21
un sentido, ahora diseñar la aplicación
00:24:23
porque estás de nuevo protegiendo
00:24:24
que se instancien objetos cuando no hacen falta
00:24:26
o no es necesario, pueden crear problemas
00:24:29
esa es la primera ventaja
00:24:30
que ya pones una restricción
00:24:32
entonces poner restricciones a nivel de código
00:24:34
viene bien
00:24:37
porque te aseguras que luego en tiempo
00:24:38
de ejecución seguramente salgan
00:24:41
menos errores, cuantas más restricciones
00:24:43
pongas a nivel de código
00:24:45
menos errores
00:24:46
incontrolados vas a tener tiempo de ejecución
00:24:48
a cambios más rollos
00:24:51
que el código, porque tienes que satisfacer esas restricciones
00:24:53
es como el diseño de bases de datos
00:24:55
las bases aprobacionales son muy restrictivas
00:24:57
tienes que poner las claves primarias
00:24:59
claves ajenas para ti y para la tarea
00:25:01
pero una vez que has hecho un diseño bueno
00:25:03
cuando ya haces las consultas
00:25:05
en SQL
00:25:07
si satisfaces
00:25:07
esas restricciones
00:25:11
los resultados van a ser consistentes
00:25:12
si hiciéramos diseños de bases de datos abiertos
00:25:15
tú harías las consultas
00:25:19
que te dieran la gana
00:25:22
y luego los resultados podrían ser consistentes o no
00:25:23
porque como has podido hacer cualquier cosa
00:25:25
pues esta es la misma idea
00:25:27
la primera ventaja es esa
00:25:28
que a nivel de escritura de código
00:25:30
de compilación estás poniendo ya una restricción
00:25:33
y eso seguramente
00:25:35
te haga pensar mejor la aplicación
00:25:36
y evitar que luego en tiempo de ejecución
00:25:39
digas, uy que cosa mala me está haciendo esto
00:25:41
esa es la primera, y la segunda
00:25:43
que es la que nos interesa a nosotros
00:25:45
ahora, la segunda
00:25:46
es que desde la clase
00:25:49
interna hay visibilidad
00:25:51
directa tal cual
00:25:53
a las variables de la clase que la
00:25:55
contiene, es decir
00:25:57
desde estos métodos
00:25:59
si a mi me da
00:26:00
la gana desde estos métodos
00:26:03
imagínate que tengo aquí un método cualquiera
00:26:05
desde estos métodos
00:26:07
yo puedo acceder a las variables
00:26:09
de la clase, por supuesto, puedo acceder a estas
00:26:11
variables como siempre pero también puedo acceder a estas propiedades a
00:26:13
éstas es decir desde esta clase interna tengo visibilidad de las propiedades de
00:26:19
la clase externa o lo que es lo mismo desde este objeto 2 puedo modificar las
00:26:26
propiedades de éste esa es la ventaja
00:26:32
este objeto 2 se convierte en dependiente su existencia depende de que
00:26:37
exista este,
00:26:42
su existencia depende de que exista este,
00:26:44
no puede ser independiente, no puedo crearle por libre,
00:26:46
no puedo hacer un new v sin que
00:26:48
exista este, no puedo,
00:26:50
su existencia depende de que
00:26:52
exista este, y a cambio
00:26:54
a través de él y de sus
00:26:56
métodos podemos modificar propiedades
00:26:58
de aquel del que depende.
00:27:00
¿Vale? No es una herramienta más
00:27:02
para diseñar aplicaciones, que nos puede
00:27:04
venir muy bien y puede encajar perfectamente
00:27:06
en lo que queremos hacer.
00:27:08
y si encaja perfectamente lo que queremos hacer
00:27:09
aparte de que el programa
00:27:12
se va a entender mejor, seguramente nos
00:27:14
vayan a salir luego en ejecución menos cosas
00:27:16
raras que no sabemos por qué salen
00:27:18
porque el diseño se ha adaptado de partida
00:27:19
a lo que queremos
00:27:22
bueno, pues esto es un poquito por encima
00:27:23
el concepto de clase interna, que es útil
00:27:26
efectivamente para diseños
00:27:28
en los cuales esto nos interesa
00:27:30
pues justo a nosotros nos
00:27:31
interesa esto, porque teníamos dos
00:27:34
clases
00:27:36
esta tenéis que verla como la frame
00:27:36
y esta como la capturadora
00:27:40
en la acción listener
00:27:44
¿qué problema teníamos? que desde esta
00:27:45
queríamos poder acceder a las propiedades de esta
00:27:47
y no podíamos, teníamos que pasárselo por parámetro
00:27:50
al constructor, lo cual es un rollo
00:27:54
sobre todo si tengo que pasar mucho
00:27:55
anda, pues meto esta dentro de la otra
00:27:57
y ya he solucionado mi problema
00:28:00
que es acceder
00:28:01
desde la capturadora, que es esta
00:28:03
desde el Action Listener a todas las del frame que son estas.
00:28:07
He solucionado de golpe ese problema.
00:28:11
La siguiente pregunta sería, hombre, ¿pero tiene sentido
00:28:13
que esta realmente depende de su existencia de la otra
00:28:16
o es independiente?
00:28:20
Hombre, claro que depende.
00:28:21
¿Qué sentido tiene que haya una capturadora de componentes
00:28:23
de un frame si el frame no existe?
00:28:25
No tiene ningún sentido.
00:28:28
Luego se adapta perfectamente.
00:28:29
La existencia de esta está condicionada,
00:28:31
solo me interesa a mí si hay un frame.
00:28:34
Si no hay un frame, ¿a quién quiero yo escuchar?
00:28:36
No quiero yo escuchar a nadie
00:28:38
Luego se adapta a la perfección
00:28:39
Lo de las clases internas
00:28:42
Porque la capturadora
00:28:43
Su existencia
00:28:46
Solo tiene sentido si existe un frame
00:28:47
Y al meterla adentro
00:28:50
Tengo acceso automático
00:28:52
A todas las propiedades
00:28:53
¿Vale?
00:28:56
Pues
00:29:00
¿Cómo sería entonces?
00:29:01
Vale, pues para no
00:29:03
Romper esta
00:29:51
Me voy a hacer otro paquete
00:29:53
Vista 2
00:29:57
Y en ese otro paquete
00:29:58
Vista 2
00:29:59
Pongo este frame
00:29:59
Pero con la captura dentro
00:30:00
Etcétera
00:30:01
Vale, pues voy a copiar
00:30:02
La ventana visiesto
00:30:15
Que tenía
00:30:16
La voy a copiar
00:30:17
Esa misma
00:30:19
En vista 2
00:30:19
Vale, pues esta es
00:30:20
Le voy a quitar
00:30:30
Todo esto verde
00:30:31
Que está en la otra
00:30:32
Ya escrito
00:30:33
¿Vale? Para que se vea mejor
00:30:35
Entonces en el constructor
00:30:40
Pongo el gestor de ubicación
00:30:41
Todos estos comentarios están en la otra
00:30:44
Así que da igual, asocio el gestor al panel
00:30:46
Añado los componentes al panel
00:30:48
Uy
00:30:51
¿Vale?
00:30:56
Y ahora esto
00:31:03
Lo vamos a quitar
00:31:05
¿Vale?
00:31:08
Entonces he añadido los componentes
00:31:13
Pero mi
00:31:14
Botón todavía no tiene añadida
00:31:16
Ninguna clase, ningún objeto de ninguna clase capturadora
00:31:18
Vale, ¿por dónde vamos a poner esa clase?
00:31:21
¿Vale?
00:31:24
Vamos a ponerla aquí dentro
00:31:25
¿Vale? Vamos a ponerla aquí dentro
00:31:27
Esa clase, entonces voy a copiar y pegar
00:31:31
Toda esta clase enterita
00:31:32
Aquí
00:31:38
La clase
00:31:41
La voy a copiar
00:31:44
Aquí dentro, ¿vale?
00:31:54
Entonces como veis no me da ningún problema
00:31:55
Es una clase interna, me ha dejado ponerla dentro
00:31:57
Sin errores y sin nada
00:32:00
¿Vale? Entonces voy a quitarle
00:32:01
Esto
00:32:04
Que es lo que quería ahorrarme
00:32:04
Haciéndolo como clase interna, el tener que pasárselo
00:32:07
Por constructor, o sea el constructor
00:32:09
Enterito, fuera
00:32:11
Solo quiero ActionPerformance, este
00:32:12
Solo quiero este
00:32:15
¿Vale?
00:32:17
Entonces, ahora
00:32:20
Esta clase interna
00:32:21
De aquí, puede acceder
00:32:23
A todas las propiedades
00:32:26
A todas de VentanaVisiesto
00:32:27
¿Vale? A todas
00:32:29
entonces, ¿cuál es la solución
00:32:31
aquí, la estructura aquí?
00:32:34
todos mis componentes, en lugar de
00:32:35
declararlos aquí, voy a declararlos
00:32:38
fuera, ya está
00:32:40
en lugar de locales, y aquí ya los
00:32:41
coloco, hago con ellos lo que quiera
00:32:44
entonces, simplemente la etiqueta
00:32:45
y con su
00:32:47
inicialización si quiero, aquí
00:32:49
fuera, ¿cuál más tenía?
00:32:51
bueno, la puedo quitar
00:33:00
ya de aquí, claro
00:33:01
bueno, la etiqueta, ¿cuál más?
00:33:01
Este, el dato
00:33:04
Control X, aquí
00:33:05
Ahí está
00:33:08
¿Cuál más?
00:33:09
Así ya me queda más cortito
00:33:12
El resultado, la etiqueta esta
00:33:14
Aquí fuera
00:33:16
Y el botón
00:33:21
Aquí fuera
00:33:26
Vale, entonces ahora me queda una estructura
00:33:33
Un poco más, un constructor más cortito
00:33:35
Ya se empieza
00:33:38
Esto ya es más fácil un poquito de entender
00:33:41
Vale, entonces yo tengo
00:33:43
Este es mi frame
00:33:45
En mi frame
00:33:47
¿Qué componentes quiero?
00:33:49
Yo los he decidido, pues estos son mis componentes
00:33:50
Pa, pa, pa
00:33:53
Además, los puedo inicializar
00:33:54
Ahí si quiero, si no da igual
00:33:57
Los inicializo ahí dentro
00:33:59
Si los puedo inicializar aquí, pues mira, eso que me quito
00:34:00
¿Vale? Mi listado de componentes
00:34:02
Ahí, pa, pa, pa, esos son tu listado de componentes
00:34:05
Ahora, el constructor
00:34:07
El constructor, pues hace ya lo que tenga que hacer
00:34:08
Hace el gestor de ubicación
00:34:11
Lo asocia al panel
00:34:13
Pega los componentes al panel
00:34:14
¿Y qué es lo único que le falta?
00:34:16
Lo único que le falta es
00:34:19
Al botón
00:34:21
Añadirle
00:34:23
Añadirle
00:34:24
Añadirle un objeto
00:34:27
De esta clase de aquí
00:34:34
Un objeto de esa clase
00:34:35
¿Vale?
00:34:37
Vale, pues vengamos a añadírselo
00:34:39
Y ya está
00:34:41
Le añado un objeto de esa clase
00:34:53
Aunque el nombre real de la clase
00:34:56
y ahora vamos a comprobar, de capturar
00:34:58
pulsar botón, será en realidad
00:35:00
ventana visiesto, captura, pulsar botón
00:35:02
como aquí lo estoy instanciando
00:35:04
desde dentro de esta, no hace falta ponerlo
00:35:06
si yo lo instanciara en otra parte
00:35:08
sí tendría que ponerlo, pero eso no lo vamos a hacer
00:35:10
nosotros, no, quiero que
00:35:12
nos liemos ahora con clases internas
00:35:14
vale, entonces ahora ya
00:35:16
le añado un objeto de esta clase que
00:35:20
está dentro
00:35:22
entonces la ventaja al estar dentro
00:35:23
es que solo necesito la acción performance
00:35:26
solo
00:35:28
y en la acción performance accedo a lo que me dé la gana
00:35:29
a todo lo del frame
00:35:33
accedo a todo, siempre y cuando lo del frame
00:35:34
esté declarado fuera
00:35:36
y esta ya es la estructura habitual
00:35:37
de swing
00:35:42
el siguiente salto, pero eso ya lo veremos con el builder
00:35:42
es que esta clase además de interna sea anónima
00:35:46
pero eso ya sería el siguiente salto
00:35:48
es otra cosa
00:35:50
lo importante es que entendáis esta
00:35:51
esta estructura
00:35:54
si nos vamos de hecho
00:35:56
para que veáis que son dos clases diferentes
00:35:58
si nos fuéramos aquí
00:36:00
a ver lo que ha generado
00:36:04
en Vista 2
00:36:14
fijaos que hay dos clases
00:36:16
en el paquete Vista 2
00:36:25
está VentanaVis y esto con la otra dentro
00:36:28
con la otra dentro
00:36:30
y yo he dicho, oye, que este dentro
00:36:31
no significa que no sean dos clases independientes
00:36:32
claro que lo son, son dos clases independientes
00:36:35
esta es una y esta es la interna
00:36:37
que en punto clas se llama
00:36:39
con un dólar dentro
00:36:41
Son dos clases separadas
00:36:42
Y yo puedo instanciar las dos por separado
00:36:45
Esta la instanciaré con new ventana bisiesto
00:36:47
Y esta la instanciaré con new ventana bisiesto
00:36:50
Punto
00:36:52
Captura pulsar botón
00:36:53
Para la instancia desde código
00:36:55
Si quiero instanciarla afuera
00:36:56
Ahora es que la estaba instanciando dentro
00:36:57
Entonces al instanciarla dentro de esta
00:37:00
Puedo instanciarla directamente con su nombre interno
00:37:02
Pero son dos clases independientes
00:37:06
bueno independientes en el sentido de que se pueden instanciar
00:37:12
por separado pero
00:37:18
esta para existir tiene que
00:37:20
existir un objeto de esta otra
00:37:22
vale entonces si ejecutamos
00:37:24
esta ahora
00:37:26
nuestro main
00:37:28
un momento ya nos vamos
00:37:29
vamos a nuestro main
00:37:33
aquí
00:37:35
nuestro main en lugar de ventana
00:37:35
si esto vamos a hacerla de vista
00:37:43
dos
00:37:45
Vista 2, la otra que he hecho
00:37:45
Vale
00:37:49
Le pongo su nombre real
00:37:53
Con el prefijo delante
00:37:56
Para que no use la que tiene el import, que es esta
00:37:57
Esta es la nueva que he hecho
00:37:59
Con la clase interna
00:38:01
Si no se nos ha escapado nada, debería funcionar igual
00:38:02
Este main, con la nueva que hemos hecho
00:38:06
Y sí, funciona igual
00:38:08
Vale
00:38:17
Pues venga, vamos a parar aquí entonces
00:38:17
- Subido por:
- Raquel G.
- Licencia:
- Todos los derechos reservados
- Visualizaciones:
- 10
- Fecha:
- 22 de abril de 2024 - 18:08
- Visibilidad:
- Clave
- Centro:
- IES ROSA CHACEL
- Duración:
- 38′ 21″
- Relación de aspecto:
- 1.78:1
- Resolución:
- 1920x1080 píxeles
- Tamaño:
- 549.86 MBytes