2024-12-02-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:
Tema 4 - Conceptos POO
Ya estamos grabando.
00:00:01
No sé si tenéis alguna duda o alguna cosita que me queréis comentar
00:00:04
antes de arrancar a contaros yo cosas por ahí del tema 4.
00:00:07
¿Alguien decía algo por ahí?
00:00:18
Ah, sí, que no hay ninguna cosa que plantear de momento.
00:00:23
Vale, pues nada, pues arranco a contaros cosas entonces.
00:00:27
Bueno, el tema 4 ya lo tenemos abierto desde la semana pasada.
00:00:35
No sé si habéis tenido oportunidad de ir echándole un ojillo. Vamos a hacer un repaso así general. Este tema 4 habla, aquí estamos, es una introducción a la programación orientada a objetos y en verdad es muy complicado arrancar la asignatura si no se empieza a hablar desde el día 1, si vas a hacer cosas con Java ya relacionada con los objetos.
00:00:38
hablar de las estructuras de control
00:01:03
que es verdad que son
00:01:06
los bucles o las condiciones
00:01:07
los if, los switch
00:01:10
porque si
00:01:11
si lo estás utilizando
00:01:13
dentro de una programación orientada a objetos
00:01:16
e intentar evitar
00:01:18
lo que son objetos y lo que son clases
00:01:19
pues en verdad es muy complicado
00:01:21
así que además
00:01:23
considero que es mejor ir introduciendo
00:01:25
todos estos conceptos desde el principio
00:01:28
así que mucho de lo que se habla aquí
00:01:29
pues ya hemos ido trabajando, en cualquier caso le damos otro repaso
00:01:32
más formal y vamos con ello
00:01:36
vamos a crear un proyecto, por ejemplo llamemos tema 4
00:01:39
y así nos vamos apoyando en el IDE para ir haciendo
00:01:48
ir comentando los diferentes contenidos
00:01:52
bueno lo primero de lo que empieza a hablar el tema 4 es la diferencia
00:01:57
entre clase y objeto, como os digo ya lo hemos
00:02:07
tratado estos conceptos, una clase vendría a ser un esquema en el cual definimos cómo
00:02:11
se van a comportar diferentes objetos dentro de nuestro programa. Cuando nosotros arrancamos
00:02:20
un programa, en realidad las clases no se activan, sino que se activan objetos que responden
00:02:25
a las características que hemos definido por una clase en particular. Eso sí, esos
00:02:31
objetos tienen un comportamiento de acuerdo a lo que esté definido en la clase. Y cuando definimos
00:02:36
la clase, recordad, decimos que se compone, digamos, por dos tipos de información. Por un lado,
00:02:42
vamos a llamar clase tarea 4 o clase persona. Por un lado tenemos características o atributos
00:02:52
de la clase y por otro lado tenemos lo que son los métodos o las acciones. Los atributos
00:03:00
son variables pertenecientes a la clase que están disponibles en el ámbito
00:03:08
de toda la clase, es decir, todo atributo que definamos para una clase estará disponible
00:03:13
para trabajar con ellos en métodos que aparezcan
00:03:17
dentro de su ámbito, es decir, de las llaves que encierran a la llave.
00:03:21
Por ejemplo, por una persona diríamos que tenemos public
00:03:25
public string para el nombre.
00:03:28
Es un clásico utilizar la clase persona cuando te pones a explicar cosas de estas.
00:03:33
Ya en este tema, pues vamos a hablar un poquito de lo que son las etiquetas public, tanto para una clase como para un método o para un atributo, como es el caso, pero ahora en un ratín, lo decimos.
00:03:38
las variables típicamente
00:03:53
si son de clase, están definidas en el ámbito de la clase
00:03:57
y si son variables que necesitamos utilizar dentro de un determinado método
00:04:01
vuelve a aparecer aquí la etiqueta public, ya os digo que ahora
00:04:05
comentamos en qué consisten las diferentes posibilidades que tenemos para utilizar public
00:04:09
o alternativas a public, voy a saludar
00:04:14
vamos a poner aquí, esto sería un método, es decir, estos son los dos
00:04:18
bloques que tenemos dentro de una clase. Fijaros que una clase no es, en este caso una clase y en
00:04:22
particular la clase persona que estamos definiendo, no es ninguna persona en particular que vaya a
00:04:29
formar, que vaya a interactuar con otros objetos de mi programa, sino que es el esquema de lo que
00:04:33
van a tener cualquiera de las personas que demos de alta dentro de mi programa, que podrán tener
00:04:40
un nombre, una edad y la posibilidad de saludar. Fijaros que, bueno, pues podríamos definir
00:04:45
variables en diferentes ámbitos. En el ámbito de la clase
00:04:53
en sí, con lo cual está disponible entre las llaves de la clase
00:04:56
y aquí podríamos definir otras variables
00:04:59
int y valor. Si fuera en un momento dado
00:05:01
dentro del saludo necesitáramos un determinado valor.
00:05:05
Esta variable está disponible para el ámbito
00:05:11
del método saludar, mientras estas otras
00:05:13
en el ámbito de la clase. Podríamos decir, bueno, pues
00:05:16
si quiero utilizarla aquí en el método saludar, me resulta
00:05:19
muy cómodo coger y definirla aquí
00:05:22
y ya está, defino aquí todas y también
00:05:24
puedo utilizar y valor aquí
00:05:26
esto tendría dos implicaciones
00:05:27
por un lado, la implicación
00:05:30
de que esta variable
00:05:33
estaría no solo disponible en el método saludar
00:05:34
si consideramos que es una variable
00:05:36
propia de este método y no de toda la clase
00:05:38
sino que otro método
00:05:40
que tuviéramos por aquí, despedirse
00:05:42
también tendría disponible
00:05:44
esa variable, que puede ser
00:05:46
que nos interese
00:05:48
ponerlo con minúscula
00:05:49
Podría ser que no nos interese y luego, por otro lado, a nivel organizativo, las variables que definamos de clase típicamente serán variables que identifiquen a las personas y no variables que momentáneamente podamos necesitar para hacer una determinada tarea, en este caso dentro del método de saludar, como podría ser la variable y valor.
00:05:55
Y valor, en el contexto de saludar, según el algoritmo que estemos desarrollando aquí para saludar, podría ser necesaria, pero y valor no sería algo que identifique a objetos de la clase persona que vayamos definiendo.
00:06:17
Entonces, bajo ese criterio tendríamos que definir los métodos de clase que sí que tengan que ver con características de las personas y si necesitamos otras variables en momentos puntuales dentro de unos métodos para desarrollar su algoritmo, pues los definimos como variables locales.
00:06:31
Dentro de lo que son la sintaxis típica que está un poco acordada a la hora de programar en Java, las clases las ponemos empezando con una letra mayúscula y los métodos con una letra minúscula, con una excepción que son los métodos constructores.
00:06:47
Los métodos constructores se tienen que llamar exactamente igual que la clase.
00:07:13
Entonces aquí podríamos definir un método, public void persona.
00:07:18
Entonces este método, lógicamente si se tiene que llamar, es un método constructor porque tiene el mismo nombre y método que la clase.
00:07:28
Si se tiene que llamar igual y nos obligamos a que las clases empiecen con mayúscula, lógicamente el método constructor tendrá que empezar con mayúscula.
00:07:36
mayúscula y se escapa de el acuerdo digamos que hay para nombrar los métodos en líneas generales
00:07:43
que deberían empezar todos con minúscula. Si ponemos una S mayúscula fijaros que no es un
00:07:51
problema en realidad para el compilador sino que más bien es un convenio a la hora de nombrar
00:07:56
las diferentes funciones en Java y que si lo vemos en minúscula pues rápidamente sepamos
00:08:02
que eso podría llegar a ser un método los métodos constructores recordad mira vamos a poner aquí
00:08:08
otra clase dentro del proyecto que sea la clase inicio vamos a llamarla por ejemplo y en esta
00:08:18
clase inicio vamos a suponer que es el punto de arranque de nuestro proyecto entonces en esta
00:08:31
clase está el método public public static o static public me parece que tiene que ir el static antes
00:08:37
después repasamos un poco toda esta cabecera
00:08:47
del método main, entonces
00:09:05
venimos diciendo que todo proyecto necesita un punto de entrada
00:09:08
que es el método main
00:09:12
aquí es donde vamos a arrancar nuestro programa
00:09:15
en este proyecto hemos definido una clase que es la clase persona
00:09:17
que tiene unas determinadas características
00:09:22
y realiza unas determinadas acciones en forma de métodos
00:09:24
que en realidad todavía no hemos programado nada
00:09:28
uno de los métodos es el método constructor
00:09:30
¿por qué? porque se llama igual que la clase
00:09:33
y luego, bueno, pues tiene otros dos métodos aquí
00:09:36
después vamos poniendo algo de código en ellos
00:09:38
que son el de saludar y despedirse
00:09:41
en nuestro programa ahora mismo, si no venimos al main
00:09:44
tenemos alguna persona que haya cobrado vida
00:09:47
digamos, y empieza a hacer cosas dentro del programa
00:09:51
para dar solución al algoritmo que estamos buscando
00:09:54
pues no, todavía no, pero si en cambio tenemos
00:09:57
un esqueleto aquí de cómo se comportan las personas, es decir,
00:09:59
el comportamiento de toda persona que definamos en nuestro programa
00:10:04
está agrupado en esta clase que es la que hemos llamado de esta forma.
00:10:07
Entonces, ¿en qué momento damos vida a una persona?
00:10:15
Pues definimos un tipo de variable que en este caso va a ser del tipo persona
00:10:19
que justo hemos definido aquí sus parámetros y sus comportamientos
00:10:25
un poquito de forma similar a como definiríamos una variable
00:10:29
de un tipo primitivo, igual que definimos aquí
00:10:34
y es una variable del tipo int, resulta que persona
00:10:38
es una variable del tipo miper, es una variable del tipo
00:10:42
persona, entonces las características que tiene miper serán las que hayamos
00:10:46
definido nosotros aquí en esta clase. Para los tipos
00:10:50
primitivos hemos hablado otros días, no es necesario hacer el new
00:10:54
para los tipos referenciados si que lo es
00:10:57
entonces la clase persona es un tipo referenciado
00:11:00
para el objeto miper
00:11:03
lo primero que tenemos que hacer es hacer un new
00:11:05
que nos hará las reservas que toquen
00:11:09
en memoria RAM para que miper sea capaz
00:11:12
de funcionar dentro del programa
00:11:15
que principalmente se entiende sobre todo
00:11:17
si nos fijamos en sus parámetros pues hará reserva para guardar
00:11:21
estos datos y luego después del new
00:11:24
Java lo que nos demanda es que
00:11:28
le ponga, llamemos a un método que haga una inicialización
00:11:33
si es que corresponde hacer alguna inicialización del objeto que estamos dando
00:11:37
de alta y esa inicialización se hace a través de los constructores
00:11:41
recordad que hemos dicho que el constructor
00:11:44
es un método que se llama igual que la clase, entonces por eso
00:11:49
justo aquí después del new solemos poner persona
00:11:53
en este conjunto lo que estamos haciendo es definir
00:11:57
en el conjunto de esta instrucción, estamos definiendo
00:12:02
un objeto llamado miper en particular
00:12:05
de la clase persona, hacemos las reservas
00:12:08
que correspondan en memoria y llamamos a un método
00:12:12
para la inicialización de este objeto
00:12:14
de la clase persona, que es el método constructor
00:12:17
¿y qué inicialización se producirá? Pues la que
00:12:20
programemos aquí. En relación a los constructores
00:12:23
fijaros que si yo comento esto
00:12:29
este persona me sigue funcionando, me sigue compilando.
00:12:36
¿Qué sucede?
00:12:43
Si, como siempre después de hacer un new en un objeto que es de un tipo referenciado,
00:12:44
como siempre vamos a llamar al constructor,
00:12:51
por defecto, aunque no lo hayamos definido,
00:12:54
en la clase, en este caso la clase persona,
00:12:56
Java entiende que hay un constructor por defecto
00:13:00
que en esa inicialización no viene a hacer nada, digamos.
00:13:03
pero para dar sentido a la sintaxis que tiene java pues existe por defecto un constructor de
00:13:08
este tipo es decir el nombre de la clase y sin ningún parámetro metido aquí en dentro de las
00:13:14
llaves si yo cojo eso es para cuando no existe el de por defecto cuando no existe definido ningún
00:13:22
constructor dentro de la clase persona si yo para inicializar la clase persona me defino un
00:13:31
constructor, pues ese que había por defecto por ahí
00:13:36
queda ya sobrescrito y el que se utiliza
00:13:39
es el que yo define aquí con el código
00:13:42
que yo ponga. Entonces, en el momento que yo ya he definido
00:13:46
un constructor dentro de la clase persona, ese constructor por defecto
00:13:57
al que estaba llamando yo antes cuando no existía ninguno, que era
00:14:01
uno por defecto y no hacía nada, deja
00:14:03
de existir para pasar a existir el que yo ponga
00:14:07
dentro de mi clase. Pero es más,
00:14:10
si yo defino un constructor
00:14:13
que dentro de mi clase que admita y ahora repasamos también estos métodos que admita información entre
00:14:16
los paréntesis ahora hablamos de qué consiste esto esto también desactiva el constructor por
00:14:32
defecto es decir definir cualquier constructor con o sin información entre los paréntesis desactiva
00:14:38
el constructor que por defecto tiene java para cuando no existe ninguno entonces en este caso
00:14:44
me sigue compilando esto, yo esperaba que no me compilase
00:14:49
pues nada de lo dicho, pues sigue compilando
00:15:02
nada, retiro lo dicho, estaba comentando que en el momento que definías
00:15:31
cualquier constructor, que en el momento que definías cualquier constructor con o sin
00:15:35
parámetros, yo pensaba
00:15:42
cosa que por lo que veo según se está comportando el código, era erróneo
00:15:45
que el constructor por defecto quedaba desactivado, en este caso
00:15:50
si hubiera sido como yo decía, esto me debería haber dado error
00:15:54
porque estoy invocando a un constructor por defecto
00:15:57
que no recibe ningún parámetro y en cambio solo
00:16:00
por código tengo definido uno que sí que recibe un parámetro
00:16:03
pero por lo que veo el constructor por defecto solamente
00:16:06
deja de tener sentido el que
00:16:09
nos ofrece Java que no hace nada
00:16:11
si lo sobrescribo dentro de
00:16:14
la clase persona, no si
00:16:17
lo sobrecargo, ahora os comento el tema de la sobrecarga
00:16:20
que es otro constructor con parámetros aquí, pues nada
00:16:24
este seguiría funcionando por lo que se ve aquí, ahora tendríamos
00:16:27
en sí dos constructores a los que podríamos llamar después del
00:16:32
new, fijaros que ambos dos son constructores porque los dos
00:16:36
se llaman como la clase persona, como la clase y este
00:16:39
objeto en el momento de inicializarlo, pues podríamos utilizar
00:16:44
el constructor que no recibe ningún parámetro, que sería este
00:16:47
y para este segundo objeto podríamos utilizar el constructor que si lo recibe vale bien ya entiendo
00:16:51
lo que me está pasando está mi error mirad los los constructores se definen sin tipo aquí ahora
00:17:14
también os comento lo que es el tipo este es public persona no public void a ver si ahora
00:17:24
así que tiene el comportamiento que yo esperaba miras efectivamente en el momento que defino
00:17:36
cualquier constructor ahora repaso lo que me estaba lo que estaba sucediendo para que lo
00:17:44
tengáis claro en el momento que yo defino cualquier constructor con o sin parámetros
00:17:49
recibiéndose por aquí entre los paréntesis el constructor por defecto deja de estar activo
00:17:53
veis ya no me compila por aquí cuando está activo cuando está disponible el constructor por defecto
00:17:58
cuando no existe ningún constructor en la clase en este caso fijaros como ahora tengo comentados
00:18:04
tanto el que no recibe parámetros como el que sí que lo recibe uno y ya me vuelvo a compilar esto
00:18:10
que era la lógica que yo esperaba antes pero mi error es que había puesto aquí un public void
00:18:15
y al momento al poner este voice aquí ya no lo consideraba como el constructor en sí porque los
00:18:21
constructores no tienen ninguna etiqueta de este tipo ahora os comento lo que es el voice este
00:18:27
Aquí lo tenemos. Bueno, pues fijaros cómo hemos dado de alta aquí a dos personas y estos objetos ya sí que son los que van interactuando durante el programa con, bueno, pues para ir haciendo cosas, pues mi per podrá saludar, mi per 2 podrá despedirse y a través de los objetos que hemos dado de alta y hemos inicializado con el constructor, poniendo aquí un punto, pues podemos hacer a sus parámetros o a las funciones que él puede hacer.
00:18:32
¿Qué funciones puede, qué métodos podemos llamar o qué funciones puede hacer un objeto? Pues los que tengamos definido dentro de la clase, más otros que están disponibles en todas las clases de que podamos, que vayamos utilizando dentro de nuestro programa, porque los tienen disponibles como consecuencia de una especie de herencia desde la clase Object.
00:19:08
Como pues el notify, notify all, toString, wait, bueno, todos estos métodos están disponibles para cualquier objeto de cualquier clase, no porque los definamos en sí dentro de la clase, sino porque nos vienen definidos, digamos, desde unas instancias superiores en una jerarquía de clases por herencia.
00:19:29
La herencia, hablaremos de ella más en detalle en siguientes temas, pero viene a consistir en que una clase que definamos, aparte de tener sus características, tiene algunas características porque son clases hijas dentro de una jerarquía de clases que va de arriba a abajo, de clases superiores.
00:19:48
Entonces la clase object es una clase definida en las librerías de Java que implementa unas ciertas cosas que interesa que las tengan disponibles todos los objetos de todos los programas.
00:20:17
Y esa es la razón por la que si ponemos aquí mi per punto, no solamente sale despedir aquí o saludar, que son métodos que he definido ahí o los atributos que tenemos por aquí, sino que nos salen otros métodos como equals, getClass, hasCode y notify que vienen heredados desde esas clases superiores.
00:20:29
Mira, más cosas. Una de las características que tenemos en la programación orientada a objeto es la sobrecarga de métodos. Persona, en este caso que es el método constructor, es un método más de la clase, entonces es posible sobrecargarlo, igual que sería otros métodos que tengamos por aquí.
00:20:50
Vamos a sobrecargar el método saludar, después os cuento para qué sirve el void este que decíamos.
00:21:20
Mira, si yo pongo este código, system.out.println, hola, en este saludo, y aquí pongo un hola2, resulta que el programa no me compila.
00:21:27
¿Y por qué no me compila? Porque si yo ahora cojo aquí y digo miper.saludar, hago una llamada para que el objeto miper salude, para saludar se tiene que ir al esquema de la clase persona a ver cómo tiene que actuar a la hora de saludar.
00:21:47
Y cuando llega aquí dice, tengo un saludar aquí y todo otro saludar aquí, que en principio van a hacer cosas diferentes.
00:22:06
Entonces hay una dualidad de posibilidades que dice, entonces, ¿qué hago? ¿Digo hola por pantalla o digo hola dos?
00:22:13
Esto no lo va a permitir el programa, el compilador nunca, porque como no sabe por dónde tirar, pues lo que nos dice es no compilo.
00:22:21
entonces que tendría que hacer definir un método diferente saludar dos para que me dejara hacer
00:22:30
los lados y saludar para que me dejas hacer el hola sería una alternativa pero ya no sería el
00:22:36
método saludar que es realmente lo que yo quiero hacer tenerlo identificado como saludar en ambos
00:22:41
casos con dos posibilidades distintas como podríamos manejarlo pues sobrecargando el
00:22:46
método saludar sobrecargar el método a saludar implica que de alguna forma cuando vayamos a
00:22:52
hacer una llamada a saludar no haya dudas de si quiere utilizar un código u otro y que técnica
00:23:00
en la que nos permite sobrecargar métodos que tienen el mismo nombre pues que reciban una
00:23:07
serie de parámetros entre los paréntesis entonces por ejemplo yo pongo aquí string ese saludo ahora
00:23:13
ya me compila, como podéis ver.
00:23:24
El hecho de que compila aquí
00:23:27
me permite que ahora
00:23:28
yo si yo llamo a mi
00:23:29
per.saludar y aquí
00:23:31
no paso ningún
00:23:34
parámetro, ninguna información,
00:23:36
ningún dato, cuando se venga
00:23:38
a la clase persona a buscar
00:23:40
que saludar ejecutar, ya no va a haber
00:23:41
lugar a dudas. Este
00:23:44
no espera recibir ninguna información,
00:23:45
con lo cual ejecutaría en este caso este
00:23:47
System.out.println
00:23:49
y este solo se ejecutará en el caso de que entre los paréntesis
00:23:51
a la hora de llamar al método saludar, pasemos un string.
00:23:56
Entonces, si yo cojo y pongo aquí, miper.saludar, buenos días,
00:24:01
ahora estoy llamando al método saludar, pasándole entre paréntesis
00:24:18
una cadena de caracteres, es decir, un string.
00:24:22
Si nos venimos por aquí, este no tiene definido ningún string aquí,
00:24:24
con lo cual no va a ser el código que se va a ejecutar
00:24:29
y este en cambio tiene definido un string que corresponde justo
00:24:31
con la sintaxis de esta llamada
00:24:35
que le estábamos pasando una cadena de caracteres
00:24:38
entonces para este saludar buenos días
00:24:41
ahora vuelvo a no haber dudas que el método
00:24:43
saludar que quiero ejecutar de la clase persona
00:24:47
es este, en este segundo caso nos dirá
00:24:50
uno o la dos
00:24:53
fijaros como si ejecutamos
00:24:55
he ejecutado el programa del otro día
00:24:58
bueno, me ha sacado aquí toda esta información
00:25:05
y fijaros en qué consiste toda esta información
00:25:20
hemos llamado a
00:25:22
dos constructores, este constructor
00:25:23
persona, fijaros como
00:25:26
tiene un hola, con lo cual el primer constructor
00:25:29
me ha mostrado este hola, al crear el
00:25:31
segundo
00:25:33
de los objetos, también he llamado al constructor
00:25:34
que no recibe ningún parámetro, aunque tengo
00:25:37
dos por aquí, me ha vuelto a escribir un segundo
00:25:39
hola, este saludar
00:25:41
al invocar este método
00:25:45
sin parámetros me ha ejecutado este saludar, me ha dicho el tercero de los olas
00:25:47
y este otro que recibía un stream buenos días
00:25:52
me ha ejecutado este otro método y ya me ha puesto el ola2
00:25:57
vale pues, que diferencia
00:26:01
en realidad, que diferencia tenemos entre llamar a uno u otro
00:26:09
pues aquí estamos, bueno antes de contaros eso, fijaros que yo
00:26:13
si yo pongo aquí saludar y le pongo aquí un número
00:26:17
en una cadena de caracteres un 2, pues tampoco me compila. ¿Por qué? Porque
00:26:21
un método saludar que recibe un valor numérico
00:26:25
aquí entero, no está considerado, no está sobrecargado
00:26:29
entre los diferentes métodos saludar que tiene la clase persona, que tiene una sobrecarga
00:26:33
entre un saludar sin parámetros y un saludar que recibe
00:26:37
un string. Pero no hay ningún saludar que reciba un valor
00:26:41
entero. Como no hay ninguno que reciba un valor entero, pues coge y este
00:26:45
no me compila. Si fuese necesario saludar pasándole
00:26:49
aquí un dato, fijaros que, ¿qué tendríamos que hacer? Pues sobrecargar
00:26:53
nuevamente saludar, fijaros que ahora vuelve a no compilarme
00:26:59
porque vuelve a haber una ambigüedad entre dos saludar
00:27:05
que los dos reciben un string, pues podría poner aquí uno que reciba un
00:27:09
entero y volvería a compilarme, ¿por qué? Porque tengo una triple
00:27:13
sobrecarga, uno sin parámetros, uno con un string y otro con un valor entero
00:27:21
Y ahora ya, aquí también, este ya no le importa, también le gusta. Bien, pues ahí tenemos la sobrecarga. ¿Qué sucede con estos? ¿Qué interés tiene, según acabo de hacer ahora, crear valores sobrecargados que reciban aquí cierta información?
00:27:25
Pues el interés puede ser el siguiente, fijaros, si yo, estas variables que definimos aquí dentro de los paréntesis se utilizan dentro del método como variables locales, si yo pongo aquí int y 1, pues 1 sería una variable tipo primitiva de tipo int y estaría disponible para ir utilizando esta variable metiendo valores, datos, utilizándolo para operaciones numéricas,
00:27:49
o lo que correspondiese dentro del ámbito del método saludar, que es donde está definido.
00:28:19
Pues estas variables que aparecen aquí entre los paréntesis son variables de ámbito local al método también.
00:28:25
Es decir, el string eseSaludo pertenece al ámbito del método saludar, de este en particular, de esta sobrecarga del método saludar.
00:28:33
De igual forma, esta variable int y valor pertenecen a este ámbito.
00:28:43
¿Y qué valor tienen? Pues por aquí podríamos ir modificándolo, podríamos poner ese saludo igual que con cualquier otra variable, pues irle dando valores aquí, información, lo que fuese, pero de partida la información que tiene con la información que se cargan en el inicio de la ejecución del método corresponde al dato que pasemos nosotros aquí cuando estemos haciendo la llamada.
00:28:48
Entonces, estos buenos días, en este saludar que está recibiendo una cadena de caracteres, este buenos días se carga directamente en la variable ese saludo.
00:29:14
entonces si yo pongo aquí un system.out.println de ese saludo, para que no me muestre más mensajes, de momento voy a quitar los constructores estos, al quitar esos dos constructores se me queda el constructor por defecto que no hace nada en código, uno disponible siempre, que no recibe ningún parámetro, ¿veis como me sigue compilando?
00:29:26
entonces si yo ahora me llamo al método que recibe
00:30:14
una cadena de caracteres en dos ocasiones
00:30:25
y en uno le paso buenos días y en otro buenas noches, durante la ejecución
00:30:28
de este saludar que recibe un string, este buenos días se cargará
00:30:33
en la variable ese saludo y en la segunda de las ejecuciones
00:30:37
lo que cargará será este buenas noches en la variable ese saludo
00:30:41
de tal forma que nos permite mostrar diferentes saludos
00:30:45
un mismo código
00:30:49
haciendo la misma llamada
00:30:52
en función a
00:30:53
la información que tengamos desde el punto
00:30:55
de la llamada
00:30:58
fijaros como si ejecutamos aquí
00:30:58
pues ahora nos dice una vez buenos días
00:31:02
y otra vez buenas noches
00:31:03
si tenemos aquí el saludar
00:31:05
este que recibe un valor
00:31:10
numérico, pues de igual
00:31:12
forma aquí podríamos coger y decir
00:31:16
vamos a mostrar
00:31:17
el valor, la misma jugada que antes
00:31:18
entonces ahora esto no escribiría siempre un valor, si ponemos aquí que escriba un 2, pues escribiría un 2, pero si ponemos sí valor, lo que nos mostrará es la información de esta variable, esta variable se carga cada vez con el dato que hemos pasado en la llamada, entonces si ahora ponemos aquí un 2 y hacemos otra llamada con un 3, veamos como la ejecución de los métodos nos muestran el dato con la información de las variables
00:31:22
En cuanto a la sobrecarga, también deciros que hemos hecho sobrecarga aquí del método saludar sin parámetros, con un parámetro, con otro parámetro, pues podemos seguir sobrecargándolo en base a que se diferencie el método saludar unas implementaciones de OTT con otras en el número o en el tipo de datos que tengamos.
00:31:49
aquí teníamos un mismo número de datos pero de diferente tipo
00:32:17
con lo cual ya no había ambigüedad aquí a la hora de llamarlo, luego tenemos también la
00:32:21
posibilidad de decir, mira pues quiero uno que
00:32:25
reciba dos parámetros, ese info, entonces
00:32:29
para llamar a este, desde el sitio donde
00:32:35
invocamos el método, pues pondríamos miper.
00:32:39
saludar, fijaros que aquí Eclipse
00:32:44
me está ofreciendo todos los métodos sobrecargados informándome de los tipos de datos que puede
00:32:46
recibir. En particular queremos utilizar este ahora, pues uno que recibe un entero y otro que
00:32:53
recibe un string. Entonces podríamos decir el valor 4 y el string buenas. ¿Y qué sucede con
00:32:58
estos dos valores? Pues supongo que ya lo iréis adivinando por lo que hemos comentado antes. Estos
00:33:08
valores, lo que hacen es directamente cargarse en estas dos
00:33:13
variables. Y valor de inicio valdrá en esta llamada
00:33:17
4 y buenas, este string se cargará en ese
00:33:21
info. Y estas dos serán dos variables locales disponibles
00:33:25
dentro del ámbito del método saludar
00:33:29
de esta versión sobrecargada del método saludar, es decir
00:33:32
en todo el ámbito de sus llaves. Aquí lo podríamos utilizar
00:33:36
para lo que lo que tocase típicamente los constructores que hablábamos antes de ellos
00:33:40
decimos que tienen el nombre de la clase y típicamente existe bueno pues el constructor
00:33:51
por defecto que es un constructor que no recibe ningún dato luego existe el constructor copia y
00:34:08
bueno podríamos llamar el constructor completo que recibe tantos parámetros el completo este sería
00:34:36
constructor copia este el constructor por por defecto y luego el que podríamos llamar
00:34:45
constructor completo que éste recibe tantos parámetros como atributos tenga definida la
00:35:03
clase este tiene dos atributos un string y una edad podría tener más si hubiera más
00:35:17
características particulares de objetos de la clase persona podría tener más en este caso
00:35:23
tiene dos, pues entonces recibiría string snom, vamos a poner, y int y et. Fijaros, tiene dos
00:35:28
atributos, voy a llamar completo, y normalmente este constructor lo que hace es, estos datos los
00:35:42
copia en las variables del objeto que estamos creando. Entonces aquí pondríamos ese nombre,
00:35:51
igual a ese nom
00:35:58
y edad igual a i ed
00:36:01
vamos a pensar un momentito en este, ahora después pasamos al constructor
00:36:10
copia, fijaros, si yo cojo y defino
00:36:20
imaginaos que doy de alta, interrumpidme si tenéis
00:36:24
alguna duda, alguna pregunta que hacerme sobre lo que os voy
00:36:30
contando, damos de alta en nuestro programa una persona
00:36:34
que llamamos MiPer. Justo a esta persona le empezamos a dar características.
00:36:45
Si decimos que tiene un nombre que es Noah y MiPer tiene una edad que es 10 años, por ejemplo.
00:36:51
Hemos dado de alta un objeto para que participe en nuestro programa
00:37:08
llamando a este constructor, ese constructor
00:37:12
es este constructor por defecto, que fijaros, no está haciendo nada, bueno, no es el de por defecto
00:37:18
lo tengo aquí escrito, pero no está haciendo nada, no he puesto código en él
00:37:22
y luego cojo y digo, esta persona, fijaros que
00:37:26
a la hora de hacer este new, me habrá hecho el sistema operativo
00:37:30
una reserva en zona de memoria, con al menos espacio donde guardar
00:37:34
estos datos, entonces, el hecho
00:37:38
de hacer el new, vamos a ponerlo aquí en esta línea, pues igual ha cogido el sistema operativo
00:37:42
y ha dicho en la posición 30.000, la que sea, ¿vale? Pongo aquí 30.000, pero sería la que
00:37:46
en la que encuentre un espacio en memoria RAM el sistema
00:37:50
operativo donde guardar esos datos. Reservo espacio
00:37:54
bueno, sí, reservo espacio
00:37:57
para una persona. El tamaño
00:38:06
de espacio que necesita reservar, pues ya se lo estará archivando el compilador
00:38:11
dejaba que serán menos para estos dos datos. Cuando cojo y escribo el nombre
00:38:15
de NOA, pues de alguna forma se habrá organizado y a partir de la 30.000
00:38:22
seguro que pondrá en algún sitio, guardará el valor de NOA
00:38:26
y cuando le pongo la edad de 10, a partir del 30.000
00:38:29
dentro del rango de memoria que haya reservado
00:38:34
pues seguro que guarda NOA y en algún sitio guardará el 10.
00:38:38
Todo este trocito está a partir del 30.000 dentro del
00:38:42
espacio de memoria que nos habrá hecho de reserva para el new.
00:38:46
Si yo cojo ahora aquí y digo miper2
00:38:49
igual a new persona
00:38:53
y ahora le paso aquí estos datos,
00:38:57
lo que estoy haciendo es con el new una reserva de memoria igual que
00:39:14
pasaba aquí para una persona, en particular va a ser para miper2,
00:39:18
es decir, esta referencia de una persona apuntará a la posición
00:39:22
que toque, y a lo mejor el sistema operativo en este caso ha dicho que es el 40.000
00:39:26
y luego llamo a un constructor que recibe
00:39:30
una cadena de caracteres y un valor numérico, este constructor
00:39:35
resulta que es uno de los disponibles aquí, porque lo tenemos sobrecargado
00:39:39
es este, fijaros como este recibe un string y un valor numérico
00:39:44
¿veis? entonces Valeria donde se cargará?
00:39:47
se cargará en SNOM y el 13 se cargará
00:39:51
en ied, ¿veis? Ahora continuamos con esa ejecución.
00:39:57
Los valores que tiene miper cuando he definido esta primera
00:40:07
persona, como hicimos el new, hemos cargado
00:40:10
en su nombre y en su edad, fijaros que son las variables de clase
00:40:15
de miper, noa y 10, es decir, los hemos cargado en
00:40:19
estas dos variables, ¿veis? Con lo cual, todo el tiempo
00:40:23
que esté disponible el objeto miper,
00:40:26
como estas variables están en este ámbito de ejecución
00:40:30
de toda la clase, los tendremos disponibles. Es decir, ese nombre
00:40:35
si no sobreescribimos su información, valdrá durante
00:40:39
toda la ejecución del objeto, si llamamos
00:40:43
a métodos, valdrá no A y la edad valdrá 10.
00:40:47
¿Qué sucede en este otro? Valeria y 13
00:40:53
que podemos pensar, y de hecho es lo que vamos a hacer, que son el nombre y la edad
00:40:56
que va a tener mi per 2, Valeria y 13 lo estamos metiendo a través del constructor.
00:41:00
Y el constructor guardará en esta variable la información de Valeria y en esta variable el 13.
00:41:06
¿Qué ámbito de ejecución hemos dicho que tienen estas dos variables que están aquí entre los paréntesis?
00:41:14
Hemos dicho que son variables locales a este método.
00:41:20
Con lo cual, una vez que se ejecute este método, estas dos variables desaparecen.
00:41:23
desaparecen. Es decir, que si este ha cogido valeria y este ha cogido 13, cuando llegue el código
00:41:27
aquí, se terminó estas dos variables.
00:41:32
Con lo cual, el nombre no está disponible si lo queremos utilizar por aquí en saludar,
00:41:36
en este otro saludar o en despedir. Para conseguir
00:41:40
que este valeria y este 13 se queden guardados
00:41:44
para el objeto miper2
00:41:47
y tenerlos disponibles en cualquier otro método de la clase,
00:41:50
que lo que hacemos es que esta información
00:41:56
y esta la guardamos en estas otras dos variables
00:41:59
que son las variables de clase. En definitiva hemos hecho
00:42:02
algo parecido en ambos casos. Hemos creado
00:42:07
un objeto miper y miper2. En este hemos
00:42:10
utilizado el constructor por defecto
00:42:13
que no hacía nada y luego
00:42:15
mediante estas dos instrucciones
00:42:19
hemos dado valor a los parámetros
00:42:20
de clase que el objeto miper de la clase persona
00:42:25
tiene. Hemos puesto noa en esta variable, en esta
00:42:29
de clase, y la edad de 10 en esta variable.
00:42:33
Como están definidas en este ámbito, no solamente están
00:42:38
disponibles en el constructor, sino que están disponibles en cualquier otro método de la clase
00:42:41
persona cuando ejecutemos ese código para el objeto
00:42:45
miper. Y en este segundo caso,
00:42:49
a todos los efectos esta línea ha hecho lo mismo que estas tres
00:42:52
para la clase miper2, luego que lo hemos hecho a través de
00:42:56
un constructor, hemos pasado estos datos por aquí, que vendrían a ser el equivalente
00:43:00
de estos dos, y la clase en este constructor
00:43:05
que como decimos, una vez termina su ejecución
00:43:09
ya que se copian en estas variables, si estas variables son de ámbito
00:43:13
local al constructor, desaparecerían, pero al guardarlas
00:43:17
en las variables de clase, pues ya las tenemos disponibles para utilizar
00:43:21
esos datos, Valeria como nombre y 13 como edad
00:43:24
en cualquiera de todos los métodos cuando estemos trabajando
00:43:28
con el objeto miper2 de la clase persona. Cuando termina
00:43:32
esta ejecución, con este new habremos hecho
00:43:38
esta reserva y aquí terminará valiendo en la memoria RAM
00:43:42
Valeria y 13, pero este Valeria y 13
00:43:46
se estarán cargando justo durante la ejecución
00:43:50
del constructor aquí. Entonces este es el que podríamos llamar
00:43:53
no me acuerdo si exactamente es completo como lo llama
00:43:59
la teoría, creo que sí
00:44:01
lo podríamos llamar completo en tanto en cuanto se utiliza
00:44:04
para copiar en el momento que estamos haciendo
00:44:08
una inicialización del objeto
00:44:11
información de tantos parámetros como
00:44:12
de tantos datos como parámetros
00:44:17
tiene la clase persona.
00:44:19
Podría haber otros intermedios, otros constructores
00:44:27
intermedios, pero ya no tienen un nombre
00:44:29
en sí. Es decir, podríamos tener uno
00:44:31
que dijese, mira, vamos a hacer
00:44:32
un constructor persona que reciba un nombre
00:44:35
y no reciba una edad.
00:44:37
Si no recibe una edad, ya no lo consideramos
00:44:41
como el constructor completo.
00:44:43
Nos serviría para, desde el momento en el que estamos
00:44:45
haciendo la inicialización, darle un nombre,
00:44:47
pero esta variable no tendría un dato.
00:44:49
Imaginaros que nuestro programa dice
00:44:51
hay un momento en el que queremos
00:44:53
que todas las personas que se dan de alta con este constructor tengan la edad de 15, pues aquí
00:44:55
podríamos poner y edad igual a 15, con lo cual estaríamos inicializando los dos parámetros, este
00:45:01
como consecuencia del parámetro que se recibe a la hora de llamar al constructor y este siempre con
00:45:09
un valor de 15, en esa situación se podría por ejemplo encontrar una tercera persona que sería
00:45:15
persona miper3, este nombre de los objetos
00:45:22
me estoy inventando unos, hacemos el new como siempre
00:45:27
y ahora llamamos al objeto persona y esta persona
00:45:31
se llama Rubén y no le pasamos un segundo parámetro
00:45:35
pues miper3
00:45:40
el string de Rubén se guardaría en la variable
00:45:44
senom, esta variable senom es local
00:45:49
a este método sobrecargado de la constructor de la clase persona,
00:45:53
con lo cual ese nom desaparece aquí, pero para dejarlo permanente
00:46:00
mientras exista el objeto miper3, lo paso a una variable de clase
00:46:05
que es del ámbito de la clase en su conjunto.
00:46:10
Es decir, copio en ese nombre ese nom.
00:46:12
Y como justo este constructor es el que hemos decidido utilizar
00:46:16
cuando creamos nuevas personas a las que les queremos añadir
00:46:20
un nombre, pero sin darles una edad
00:46:23
por defecto le consideramos una edad 15, imaginaos que eso es lo que
00:46:26
dijese nuestro enunciado del ejercicio, pues aprovechamos
00:46:29
y en el constructor que es momento de inicialización
00:46:32
del objeto, decimos que su edad y edad sea 15
00:46:35
ahora este
00:46:38
ya no sería ninguno de los que
00:46:41
tenemos digamos más estándar, el de por defecto que no recibe nada
00:46:44
el de copia que ahora os cuento y el completo
00:46:47
que tendría tantos parámetros de entrada
00:46:50
como atributos tiene la clase
00:46:53
si tuviéramos 10 atributos aquí, pues fijaros si habría
00:46:55
combinaciones de posibles constructores, un constructor
00:46:59
que le pasas 9 y uno se queda por defecto, otro que le pasas
00:47:02
7, otro que le pasas 7 pero diferentes a los 7
00:47:05
anteriores, habría muchas posibles
00:47:08
combinaciones de posibles parámetros sobrecargados
00:47:11
estos 3, el de por defecto
00:47:16
el completo y el copia. Fijaros, el copia lo que recibe como parámetro es otra persona, ¿veis? Aquí.
00:47:20
Si tenemos aquí, vamos a repasar, este me ha dejado de compilar, sí, porque lo he borrado.
00:47:37
Mirad, vamos a ver el constructor copia. Creamos una primera persona según este modelo, según el constructor por defecto,
00:47:49
el que no recibe ningún parámetro.
00:47:58
Y ahora vamos a crear una segunda persona,
00:48:02
igual a new, persona,
00:48:07
y queremos utilizar el constructor copia.
00:48:09
¿Qué recibe el constructor copia?
00:48:11
Fijaros, recibe una referencia a una persona.
00:48:13
Entonces aquí podríamos poner una referencia a una persona.
00:48:19
¿Quién es una persona anterior que ya existe en mi programa?
00:48:21
Mi per, ¿veis?
00:48:24
Entonces aquí podemos poner mi per.
00:48:26
El programa me compila.
00:48:31
¿Y esto qué sentido tiene?
00:48:33
Pues fijaros, miper es una referencia, es un dedito, es un puntero que está señalando el lugar en la memoria RAM donde se nos ha producido la reserva. ¿Para qué? Para guardar para miper su nombre y su edad.
00:48:34
Es decir, mi per, según este desarrollo de ejemplo que estamos poniendo, sería 30.000. Sería posición de memoria 30.000. A partir de ahí es donde están los datos del objeto mi per. Es decir, a partir de ahí es donde, por ser una persona, mi per tendrá guardado su nombre y su edad.
00:48:51
aquí justo a este constructor de la clase personal le estoy pasando
00:49:10
un valor de una referencia a una persona, es decir, en este caso
00:49:17
porque es el que hemos elegido, hemos hecho el supuesto que nos ha dado
00:49:21
el sistema operativo, es mi per que apunta en la RAM al 30.000
00:49:25
entonces igual que en estos casos, esto era un string que se copiaba en la variable
00:49:28
local que tenemos en el método, pues
00:49:33
esta referencia se copia en la variable local que tenemos en el método constructor
00:49:36
Es decir, aquí P tendrá la posición, tendrá la referencia a donde apunta quien ha llamado y quien ha llamado justo en esta ocasión, porque fijaros que este constructor lo vamos a llamar ahora después más veces, pues en esta ocasión ha llamado mi per.
00:49:40
Entonces, para este caso en particular, p apuntará al mismo sitio donde mi per. Entonces, ¿dónde estará apuntando p? Pues en esta ejecución en particular, para esta, que estoy haciendo aquí, estará llamando p, apuntando p a 30.000.
00:50:01
entonces si yo ahora cojo y digo ese nombre
00:50:21
fijaros, este ese nombre
00:50:25
a quien corresponde, a este atributo
00:50:27
de la clase persona y este
00:50:30
constructor lo estamos llamando para quien, lo estamos llamando
00:50:33
para miper2, con lo cual
00:50:36
si miper2 en el new ha sido 40.000
00:50:39
me dio 40.000 la reserva
00:50:43
ya os digo que 30.000 y 40.000 son datos
00:50:45
inventados, el sistema operativo nos dará el que
00:50:49
el que le parezca según los espacios
00:50:51
que encuentren memoria RAM disponibles en cada momento
00:50:53
no tienen
00:50:55
por qué ser estos números redonditos
00:50:57
que os voy poniendo en el ejemplo
00:50:59
entonces, ese nombre
00:51:00
e iedad
00:51:05
estarán
00:51:08
a partir del
00:51:09
40.000 en una zona de memoria
00:51:11
con un espacio suficiente para guardarle
00:51:13
ese nombre y la iedad
00:51:15
¿de quién? de miperdos
00:51:17
entonces si yo pongo aquí
00:51:19
ese nombre, este ese nombre
00:51:21
corresponderá a ese
00:51:23
posible, ese nombre que tenemos aquí
00:51:25
colgando del 40.000
00:51:27
y aquí diremos que sea igual a
00:51:28
p.eseNombre
00:51:31
p donde nos apuntaba
00:51:33
a 30.000
00:51:36
y a partir de ese 30.000
00:51:38
tiene un nombre, pues el nombre que hay
00:51:43
colgando de 30.000
00:51:45
que es
00:51:46
noa, como veis aquí
00:51:48
esa información del string lo copia
00:51:50
en el nombre perteneciente al objeto que está haciendo la llamada
00:51:52
al constructor, que es miper2.
00:51:57
Con lo cual, lo que estamos haciendo es poner aquí noa.
00:51:59
Y luego cogemos y hacemos aquí uniedad igual a p.iedad.
00:52:06
Nuevamente, p donde apunta a 30.000.
00:52:15
Colgando de 30.000, según la estructura que nos haya dado
00:52:17
el sistema operativo para hacer la reserva para las variables
00:52:21
de clase, hay una edad.
00:52:24
aquí que hemos puesto este 10, que cuelga de 30.000, fijaros
00:52:26
entonces coge este 10 y lo copia ¿dónde?
00:52:30
en iedad, iedad ¿quién es?
00:52:33
esta iedad, ¿de qué objeto está llamando al constructor
00:52:35
en este momento? miper2, que está en el 40.000
00:52:39
entonces 40.000
00:52:42
con el desplazamiento necesario para guardar la edad
00:52:43
nos guardará el dato de 30.000 con el desplazamiento
00:52:47
de la edad, es decir, nos copiará aquí el 10
00:52:51
Entonces, para todos los atributos que tengamos en una clase, el constructor copia lo que hace es guardarnos la información de este objeto que le pasamos como parámetro en los atributos que tiene el nuevo objeto que estamos creando.
00:52:53
Por eso se llama constructor copia. Copiamos la información de este objeto en el nuevo objeto y en todos sus parámetros. Este es el copia.
00:53:14
Si aquí cogiésemos, si hiciésemos persona miper3 igual a new persona y le pasamos p, por ejemplo, de nuevo, miper, perdón, miper2, por ejemplo.
00:53:25
Ahora, para esta ejecución, miper2, que hemos dicho que vale 40.000.
00:53:54
para miper3, gracias a este new
00:53:59
nos hará una reserva, sistema operativo de espacio de memoria
00:54:02
vamos a suponer que sería el 50.000
00:54:06
vamos a dividir de 10.000 en 10.000
00:54:08
con un trozo de memoria por aquí reservado
00:54:09
para guardar información para sus atributos
00:54:13
es decir, para su nombre y para su edad
00:54:17
nombre y edad de quien? de miper3
00:54:19
al constructor le pasamos como referencia
00:54:22
un objeto de una clase persona, miper2 donde apunta
00:54:25
al 40.000. Entonces, en esta segunda ejecución P, en la primera ejecución apuntaba a quien la
00:54:28
había llamado, en ese caso era mi per, pues en este caso, en esta segunda llamada es a mi per 2,
00:54:40
que es en el 40.000. Entonces P sería 40.000 ese nombre, que bueno, como es copia desde el primero,
00:54:45
los datos van a ser los mismos de nuevo, pero en este caso no los va a estar copiando de aquí,
00:54:53
sino que lo va a estar copiando de aquí.
00:54:57
Lo pondría aquí en el 50.000 NOA
00:54:59
y luego la edad sería el 40.000
00:55:00
y la IEDAD a copiarlo en la edad del nuevo.
00:55:07
Con lo cual tendríamos aquí un 10.
00:55:10
Constructor copia.
00:55:14
¿Se entiende?
00:55:17
Más o menos.
00:55:18
Miren el chat, a ver si me decís alguien algo por ahí.
00:55:21
Bueno, pues, a ver, al final yo os voy contando,
00:55:33
bueno, me preguntan para la grabación
00:55:37
que qué sentido tiene poder hacer la copia al final os voy enseñando aquí un poco herramientas
00:55:39
que luego bueno pues pueden pueden ser útiles en algún momento no sé al final hay que hay que
00:55:46
buscar enunciados donde pueda esto tener sentido decir ah pues me viene bien utilizar un constructor
00:55:54
copia. Imaginaros que estamos aquí en clase y tenemos lo que es personas son los alumnos y
00:55:59
resulta que todos los alumnos tienen en lugar de dos parámetros como aquí pues tienen 15 parámetros
00:56:11
y de esos 15, 13 son comunes podrían ser. Pues bueno podríamos utilizar dar de alta 1 aquí y
00:56:18
luego utilizar el constructor copia y hacer las pequeñas modificaciones sobre el nuevo que
00:56:27
correspondiese o yo que sé imaginaros que no sé a ver qué deciros imaginaos que es una clínica
00:56:31
veterinaria y estamos dando de alta cachorros de que tiene pues no sé una mamá perrito no y tiene
00:56:45
10 cachorros y en el mundo de en el momento de partida pues todos los consideras con los mismos
00:56:55
datos. Pues bueno, pues podrías dar de alta uno de los cachorros y luego
00:56:59
dar de alta 10 objetos nuevos, utilizando el
00:57:04
constructor copia, para que los 10 cachorros en ese momento inicial al menos
00:57:07
tuvieran todos el mismo valor. Y luego ya, bueno, pues según vaya evolucionando
00:57:11
el programa, pues a lo mejor alguno irá cambiando sus datos, como podría ser
00:57:16
aquí miper2.el, la edad, pues si cambia de 1, pues cambiarlo
00:57:20
a 15. En este caso ya sobreescribiríamos
00:57:24
la edad que tenía en el constructor copia los constructores son una inicialización de
00:57:27
el objeto según lo estás creando y bueno pues puede ser que en un momento dado fijaros que
00:57:33
sobrecargados tenemos mil alternativas de poner constructores uno que no tenga ningún dato bueno
00:57:40
pues ya se irán rellenando sus parámetros según vaya evolucionando el programa podemos tener
00:57:46
algunos, según nuestro enunciado, que
00:57:51
tenga todos los datos, que
00:57:53
vendría a ser como un constructor copia, pero en lugar de pasar la referencia
00:57:57
pasar todos los datos. Podríamos tener algún constructor
00:58:00
que tuviera un conjunto
00:58:03
de parámetros que no fuesen todos ellos, pero
00:58:05
unos cuantos. Y el definir uno,
00:58:09
dos, diez o los que sean, pues irá
00:58:12
en función a lo que nos demande el enunciado.
00:58:15
Y en un momento dado, pues a lo mejor podría ser que
00:58:18
de unos como base queramos sacar copias para no tener que estar rellenando todos sus parámetros
00:58:20
de golpe pues bueno de partida en el momento inicial aquí es una copia exacta todos sus
00:58:27
parámetros pero a partir de aquí el programa pues podría ir evolucionando cambiando ciertos
00:58:33
parámetros según lo vayamos necesitando y entre todos ellos pues bueno hay tres que se definen
00:58:38
digamos que se les ponen nombres y apellidos porque sí que son siempre iguales el de por
00:58:45
defecto, que es el que no recibe parámetros, el constructor
00:58:49
copia, que es el que recibe una referencia para hacer una copia exacta
00:58:53
de todos sus atributos en el nuevo objeto con el que recibimos por aquí, y el
00:58:57
completo, que en principio se utiliza un poco para lo mismo, pero en lugar de pasar
00:59:01
una referencia a un objeto, pues se le
00:59:05
pasan todos los atributos.
00:59:09
Mirad, más cosillas que os
00:59:24
voy contando. Cuando nosotros estamos definiendo en una clase
00:59:27
su asignatura o su cabecera, típicamente aquí los constructores
00:59:33
no, ahora después llegamos a los constructores. Aquí, bueno,
00:59:40
pues ponemos, ponemos public y ponemos aquí algo. Hasta ahora
00:59:43
casi siempre suele ser el void. Fijaros que main también tiene
00:59:48
void aquí. Los métodos, a la hora de salirnos de un método,
00:59:51
¿Cuándo termina un método?
00:59:57
En el que ponemos aquí la etiqueta void
01:00:00
Pues cuando se realiza toda su ejecución
01:00:02
Y existe la posibilidad de
01:00:04
Utilizar la etiqueta return
01:00:06
La etiqueta return lo que hace es
01:00:09
Me salgo del método
01:00:10
Donde la encuentre
01:00:12
De hecho, si yo pongo aquí
01:00:13
System.out.println
01:00:14
Fijaros que Eclipse me dice
01:00:17
Oye, mira, esto no tiene ningún sentido
01:00:23
Esto que estás haciendo
01:00:24
Porque has puesto aquí una instrucción
01:00:25
Y este código es código muerto
01:00:27
Aquí el programa nunca va a llegar
01:00:28
porque se encuentra antes un retorno esto si quiero que me compile pues bueno pues podría
01:00:30
poner aquí y y igual a 2 poner aquí y y es igual a 2 fijaros cada día si me compila y en cualquier
01:00:35
caso este código según está puesto ahora mismo esto nunca se ejecutaría porque se cumple este
01:00:57
if y siempre se va a salir por el return pero ya el compilador de java o eclipse no se fija en este
01:01:01
caso no se preocupa de evaluar esto sino que ya ve que sí que hay alguna alternativa porque hay
01:01:09
un if y este return está dentro de una estructura de selección con lo cual podría no ejecutarse
01:01:14
siempre imaginaos que esto en lugar de cogerlo por aquí lo estuviéramos cogiendo con un escáner
01:01:20
el valor de i, pues una vez podríamos meter un 2 y otra vez podríamos meter un 5
01:01:25
entonces como ya no siempre sale por el return
01:01:30
esta instrucción podría haber, aunque en este código sí que pasa
01:01:33
tal cual está porque siempre iba a valer 2 si no lo modificamos
01:01:38
pero imaginaos, ya os digo que no, imaginaos que
01:01:41
este código lo tenemos aquí y en lugar de si ponemos iValor
01:01:44
pues aquí ya se da un caso en el que no siempre iValor puede valer 2
01:01:59
porque dependerá del dato que hayamos puesto nosotros cuando hayamos
01:02:05
hecho la llamada, una vez será 2 y otra vez será 10, entonces no siempre
01:02:09
saldría por aquí, ya habría opción de que esto se ejecutase, con lo cual ya me compila
01:02:13
pero resulta que si este valor es cierto, esto no va a suceder
01:02:17
esto se va a salir con el return y no va a pasar por aquí, vamos a hacer
01:02:21
esa ejecución, vamos a poner mi per
01:02:25
punto saludar, ponemos aquí un 2
01:02:30
y lo vamos a poner aquí, un 3.
01:02:36
Vamos a hacer dos llamadas, una que vale 2 y otra que vale 3.
01:02:39
Entonces, la que vale 2, vamos a mostrar aquí el valor.
01:02:43
Una vez valdrá iValor2 y otra vez valdrá iValor3.
01:02:53
Cuando valga 2, se va a salir, y cuando valga 3, no se va a salir,
01:02:58
nos va a mostrar también este mensaje.
01:03:01
Entonces, hacemos esa ejecución, ahí lo tenéis.
01:03:06
Cuando vale 2, nos ha mostrado este iValor2,
01:03:08
pero como era 2, se ha salido con el return y nos ha mostrado este mensaje.
01:03:14
Cuando valía 3, me ha mostrado el 3 y luego me ha mostrado el mensaje.
01:03:17
Es decir, return nos saca de la instrucción, nos saca del método.
01:03:23
No es muy aconsejable poner returns por ahí entre medias del código.
01:03:28
Una vez dicho su función de return, poner returns por aquí por la mitad del código,
01:03:33
porque si este código es muy largo y hace muchas cosas, una cosa así tan sencilla,
01:03:38
podemos perder la referencia de los puntos de salida de los métodos entonces se suele aconsejar
01:03:43
evitar el uso de return así tal cual y que y provocar que el método termine siempre al
01:03:48
finalizar aquí en este en este espacio eso es la recomendación general cuando éste cuando el
01:03:57
método indica que devuelve void quiere decir que este método no devuelve nada es decir cuando lo
01:04:06
llamamos, no se espera ningún retorno
01:04:13
de él. Claro, si ponemos aquí un tipo int,
01:04:17
podríamos poner cualquier tipo, tipos primitivos o tipos referenciados, lo que
01:04:21
pretende decirnos es que saludar va a devolver
01:04:25
aparte de hacer lo que tenga que hacer por aquí, recibiendo información
01:04:29
como variables locales aquí entre paréntesis, va a ser capaz de
01:04:33
devolver un dato, un dato que será de tipo entero
01:04:37
Y para que devuelva algo, utilizamos el método return, pero en este caso no nos vale un return sin ningún dato, porque se espera que retorne, que devuelva un valor entero y se lo tenemos que indicar aquí.
01:04:40
Entonces vamos a poner aquí un 1, ¿veis? Ahora ya me compila. Devuelve un 1. ¿Qué hará esta instrucción? Aparte de sacarnos del código, devuelve un 1. Ahora vemos dónde capturamos este 1.
01:04:57
típicamente igual que antes con el consejo que os daba el return es que los return aparezcan al
01:05:09
final del método no en cualquier sitio por el intermedio para que no se nos salga de un método
01:05:16
en sitios que sea más difícil de localizar el por qué se ha ido cuando estemos haciendo un
01:05:22
mantenimiento o un testeo del programa este return que es un entero aquí se captura justo en el sitio
01:05:27
de llamada y lo devuelve la llamada hacia la izquierda.
01:05:35
Es decir, nosotros aquí estamos llamando
01:05:40
al método. Fijaros, estamos llamando al método
01:05:41
que recibe como parámetro un entero
01:05:44
que corresponde a este, con lo cual el que nos está ejecutando es este.
01:05:45
Antes teníamos aquí void que no devolvía nada
01:05:51
pero ahora hemos dicho que devuelve un entero.
01:05:53
Y si ya le decimos que devuelve un entero, es obligatorio meter una instrucción
01:05:56
return para que nos compile.
01:05:59
Y es necesaria una instrucción return
01:06:02
junto con un valor del tipo que hayamos indicado aquí en la cabecera
01:06:05
que devuelve. Si ponemos ahí un return1, ya le va gustando. ¿Por qué?
01:06:10
Porque un 1 es un valor de tipo entero.
01:06:15
Esto que devolvemos, ¿dónde lo tenemos? Pues lo obtenemos
01:06:19
en la llamada y es como si lo ejecutase y lo devolviese hacia la izquierda.
01:06:23
Entonces, si yo pongo aquí un int y
01:06:28
valor devuelto, una vez que se ejecute este,
01:06:31
hace la llamada para el método saludar del objeto
01:06:37
miper, hará todo el código que sea
01:06:42
en el momento en el que hace un return, con lo cual termina el método y devuelve un 1
01:06:45
tipo entero, valor que lo devuelve
01:06:49
en la llamada hacia la izquierda, con lo cual lo estoy cargando en esta variable
01:06:56
yo podría poner aquí un system.out.println
01:07:00
valor devuelto, entonces si yo ejecuto
01:07:04
ahora, ¿veis? Valor devuelto, 1, 1. Este valor devuelto
01:07:24
es como consecuencia de este, ¿y por qué me ha puesto aquí
01:07:32
1, 1? Porque lo que ha cargado y valor, que es lo que me ha devuelto, saludar 2.
01:07:36
Imaginaos que este saludar, en lugar
01:07:43
de ser un método saludar, pues fuese algo que
01:07:47
bueno, algo que tiene alternativas, ¿no? Imaginaos que
01:07:50
estamos intentando pedir nombres, imaginaos que
01:07:54
estamos pidiendo nombres por teclado y pues con el escáner hacemos la solicitud y hay un
01:07:59
momento en el que decimos y si el nombre este en este nombre que no voy a ponerme no voy a
01:08:05
poner por teclado por no andar enredando porque ya lo conocemos imaginaos que lo estamos cogiendo por
01:08:13
ejemplo por teclado vale una varía y lo cargamos en una variable ponemos aquí que se puede recibir
01:08:17
a Ana en un caso y en otro caso se pueda recibir Mila, por ejemplo.
01:08:24
Entonces podríamos decir, sí, ya os digo que aquí lo he puesto
01:08:32
de esta forma, pero aquí podríamos poner un escáner para que esto
01:08:36
fuera variable entre los nombres que se fueran metiendo.
01:08:39
Entonces pusiéramos aquí, si ese nombre, punto, equals a Ana,
01:08:43
aquí podríamos hacer lo que tocase con Ana, guardarlo en una base
01:08:53
de datos, en un fichero, hacer el procesamiento que fuese,
01:08:56
pero podríamos querer que aparte de hacer lo que fuese
01:08:59
por aquí, que desde el sitio donde se llama
01:09:03
fuésemos capaces de saber si se ha devuelto Ana o se ha escrito
01:09:07
Ana o se ha escrito Mila, pues entonces podríamos coger e identificarlo
01:09:11
de esta forma, es decir, en ese caso return un 1
01:09:15
un 1 es un código que estamos asociando a Ana
01:09:20
else, si no
01:09:24
un return de un 2
01:09:28
y un 2 podría ser un código que
01:09:31
estuviésemos asociando a Mila
01:09:33
fijaros que ahora como hay
01:09:35
dos return aquí
01:09:39
en una instrucción
01:09:40
de selección
01:09:43
y no hay más alternativas que estar 2
01:09:45
esto vuelve a no compilarme, ¿por qué?
01:09:47
porque dice aquí este código es muerto, aquí nunca va a llegar
01:09:49
el código, vamos a quitarlo de momento
01:09:51
entonces aparte de hacer aquí lo que quisiésemos
01:09:53
porque es Ana y porque es Mila
01:09:58
pues a lo mejor guardar
01:10:00
en un fichero hola, porque Ana
01:10:01
siempre dice hola. Y en este caso podríamos guardar en un fichero adiós, porque
01:10:07
Mila siempre se despide. Aparte de eso, puede ser que
01:10:11
esas son las acciones que queremos que pasen aquí en el método saludar, pero puede ser que
01:10:15
aquí, según haya sido uno u otro, haya sido Ana o Mila,
01:10:19
podemos coger y decir, mira, queremos que pasen también cosas. Entonces aquí podríamos hacer
01:10:23
una valoración de if y valor de if
01:10:27
es igual a 1, entonces sé que ha sido Ana
01:10:30
y si no, si no es 1 es porque será 2
01:10:35
en este caso no hay más alternativas porque saludar solo devuelve eso
01:11:00
entonces vamos a hacer una ejecución con Ana, dato que podríamos por ejemplo
01:11:04
estar cogiendo el de teclado, aquí lo tenemos puesto a fuego digamos en la variable
01:11:14
entonces hacemos una ejecución con Ana, pues fijaros como
01:11:19
nos dice aquí ha sido Ana, y si en cambio
01:11:22
ponemos aquí que sea mila, pues nos dice así dos mila
01:11:26
es decir, gracias al valor devuelto por un método
01:11:36
que lo devuelve con el método, con la instrucción
01:11:41
return y en el sitio de la llamada lo devuelve
01:11:45
hacia la izquierda una vez que termina, aquí ponemos una variable del mismo tipo que devuelve
01:11:49
pues lo podemos capturar y aquí seguir haciendo un procesamiento
01:11:53
en función de lo que haya pasado aquí, algo muy típico pues imaginaros que
01:11:57
más que aquí el ejemplo este de Mila y Ana, pues imaginaros
01:12:01
que esto es insertar en base de datos
01:12:05
un dato, una información. Pues durante la
01:12:08
inserción en la base de datos, para ver si se queda registrado,
01:12:11
puede ser que de repente no haya acceso a la base de datos
01:12:14
y no se puede hacer. Pues a lo mejor nos devuelve en ese caso el método
01:12:17
en este int que he puesto un 1 para Mila
01:12:20
y un 2 para Ana, pues nos puede devolver el código 65
01:12:23
que es imposibilidad de acceder a la base
01:12:26
de datos y el código 66 que es
01:12:29
vamos, que podría ser según
01:12:32
tuviéramos definido en
01:12:35
una serie de posibles errores
01:12:36
al acceder a la base de datos, el 66 que pudiera ser
01:12:41
no tienes privilegios para insertar registros
01:12:44
en la base de datos y a lo mejor el código 0 cuando ha ido bien
01:12:47
pues entonces, si de la llamada
01:12:50
al método, en este caso saludar, que sería
01:12:53
insertar en base de datos, aquí nos devuelve
01:12:56
un cero, pues podemos decir el proceso ha ido correcto
01:12:59
y si nos devuelve un valor distinto, pues a lo mejor podemos
01:13:02
no seguir haciendo ciertas operaciones que vendrían
01:13:05
a continuación de haber hecho esa inserción en la base
01:13:08
de datos. Aquí, fijaros que antes os he dicho
01:13:11
no es muy aconsejable ir poniendo returns
01:13:16
por ahí por el código. ¿Cómo sería la forma correcta
01:13:19
para intentar evitar que esto pasase?
01:13:22
Poner un solo return al final que es
01:13:26
lo que está más aconsejado, pues mirad lo que podríamos hacer es lo siguiente
01:13:28
para poner un solo return y tener la garantía de que se nos va a ir
01:13:33
justo antes de finalizar el método, lo que podríamos hacer aquí
01:13:36
es definir una variable aquí int i result del mismo
01:13:40
tipo que el que tenemos aquí y aquí en lugar de ir haciéndolo return
01:13:46
pues hacer aquí un i result igual a 1
01:13:51
que es el que identifica en este ejemplo que ha sido
01:13:55
ana y poner aquí un irresult
01:13:58
igual a 2, ahora no nos compila, fijaros que no nos compila ahora mismo
01:14:01
el método, ¿por qué? porque esperamos que devuelva un entero
01:14:07
y como no estamos con un return devolviendo un entero, pues no se queja, pero
01:14:10
lo que vamos a poner aquí es un return de irresult y así
01:14:14
conseguimos que solamente hay un return en todo el método, vamos guardando el valor
01:14:20
que luego vamos a devolver en una variable que podemos definir aquí en la cabecera
01:14:24
del método, en la parte de arriba, y luego hacer un return de esa variable.
01:14:28
Igual que aquí estamos devolviendo un int, cuando no nos interesa que un método devuelva nada,
01:14:37
simplemente queremos su gestión, lo que tenga que hacer por aquí según su algoritmo,
01:14:42
pero que no devuelva nada, porque no hay nada pendiente que hacer según le haya ido al método,
01:14:47
pues en ese caso es cuando utilizamos la etiqueta void.
01:14:52
Y si en lugar de devolver un entero queremos que devuelva otro tipo de datos,
01:14:57
pues puede ser otro tipo de datos puede haber un método saludar que devuelve un string pues entonces pondremos aquí
01:15:01
public
01:15:07
string
01:15:09
saludar vamos a poner esta string
01:15:10
en este caso lo que devolvería sería un string y ahora ha dejado de compilarme porque lo que estoy devolviendo aquí es un tipo de
01:15:18
datos numérico cuando lo que le he dicho aquí en la
01:15:26
cabecera en la firma del método es que se espera que devuelva un string
01:15:29
bueno en este caso si es lo que nos interesa se podríamos poner aquí un string ese result un
01:15:33
poco llevando la misma funcionalidad de antes no entonces esto tendría que devolver tendría
01:15:46
que ser una variable de este tipo string y luego devolveríamos aquí ese resulto y un método puede
01:15:53
devolver tipos primitivos o puede ahora este no le gusta aquí porque ya esto como devuelve un
01:16:06
string y estoy cargando un entero pues ya dice que no vamos a poner esto para que compile si
01:16:13
no pongo nada aquí a la izquierda de la llamada que supone pues que el método en verdad devolverá
01:16:24
el string en este caso el entero antes pero como no lo capturó por aquí en ningún sitio pues como
01:16:29
que se pierde y luego también podríamos tener la posibilidad de devolver tipos referenciados
01:16:35
Esto en realidad podría devolver una referencia a una persona. Imaginaos que estamos en un contexto en el que es un club de patinaje y es un método donde damos de alta a nuevos socios.
01:16:45
entonces este método podría ser el método de dar de alta, por aquí podríamos ir
01:17:04
recuperando todos los datos que iríamos cargando en un objeto de la clase
01:17:08
persona y luego el return nos podría devolver
01:17:12
ese objeto, entonces estaríamos devolviendo en lugar de un entero o un string
01:17:17
como antes, estaríamos devolviendo una referencia a una persona
01:17:20
para asignársela a una persona que hayamos dado por aquí de alta, sería una
01:17:24
referencia parecida a la que estábamos pasando aquí como parámetro de entrada
01:17:30
la posición de memoria de una persona que se ha creado en ese caso
01:17:34
dentro del método, la estoy devolviendo para que esté disponible
01:17:39
desde el sitio donde se llamó, es decir, digamos la operación inversa
01:17:43
lo que hemos hecho cuando lo hemos pasado como parámetro. Aquí
01:17:47
una persona de alta en el ámbito este del main
01:17:50
se lo estábamos pasando para que estuviera disponible su posición de memoria
01:17:55
y poder trabajar con ella dentro del método. Y lo otro
01:17:59
si devolvemos con el return una referencia a una persona, lo que estamos haciendo es dar de alta a la persona en el método y con el return devuelvo la posición de memoria para que pueda estar disponible desde donde se llama.
01:18:03
en este caso sería desde el main, si se entiende, por ahí bien, mira si nos venimos aquí al método
01:18:18
main tenemos aquí un touch un poco grande de información y de etiquetas aunque de bastante
01:18:39
ya hemos ido hablando, fijaros main que lo hemos escrito muchas veces hasta ahora pero no habíamos
01:18:51
no nos habíamos parado a repasarlo es un método que devuelve void, como devuelve void fijaros que
01:18:56
cuando ponemos por aquí el main nunca tiene un retorno es necesario podríamos poner un
01:19:03
retorno cuando cuando no devuelve nada puedes poner el retorno y le vale o no ponerlo y ya
01:19:08
está y cuando llega aquí termina si devuelve algo no nos vale no poner retorno obligatoriamente
01:19:15
tenemos que poner un retorno con el tipo de datos entonces main es un boite fijaros como el método
01:19:20
main para su ejecución recibe aquí una información
01:19:26
que será, en este caso es
01:19:29
args es un array
01:19:34
de cadenas de caracteres. Entonces
01:19:37
args será una variable de este tipo, como
01:19:40
decimos, array de cadenas de caracteres que estará disponible como
01:19:43
variable local dentro del ámbito del main,
01:19:46
es decir, entre esta apertura de llave y este cierre.
01:19:49
Lo mismo que decíamos aquí.
01:19:53
Ese saludo, en este caso era un string disponible
01:19:57
como variable local en el ámbito de este método saludar, entre su apertura
01:20:00
y cierre de llaves. En estos métodos, saludar
01:20:03
cuando cargábamos este dato, lo cargábamos en el momento en el que hacíamos la llamada
01:20:10
a saludar, que era tal que por aquí, en estos ejemplos
01:20:14
que teníamos por aquí. Aquí llamamos al método saludar y en la llamada le pasábamos
01:20:18
el dato que se va a cargar como
01:20:23
la información que se va a cargar en esta variable, que es una variable local a la ejecución del
01:20:26
método. En main, exactamente lo mismo. Aquí tenemos una variable que se carga en el momento en el que
01:20:30
main es llamado. Lo que pasa es que el main, justo como es el punto de entrada del programa, no es código
01:20:38
que pongamos nosotros para llamar, sino que directamente se llama en el momento en el que se invoca el
01:20:44
programa. Con lo cual, ¿en qué momento ARS-S cogerá información para su ejecución? Pues la coge en el
01:20:49
momento en el que estamos lanzando su ejecución y en alguna práctica anterior creo que habíamos
01:20:56
hablado que si nosotros venimos aquí a invocar la llamada a nuestro programa vamos al word
01:21:03
escape base de eclipse como hemos dicho otras veces vamos al ejercicio con el que estamos entre
01:21:16
manos tema 4 ls dentro del proyecto tema 4 tenemos en src los códigos fuente los puntos java y en el
01:21:20
los ejecutables. Fijaros que tenemos la clase inicio
01:21:29
y la clase persona, con su extensión .class
01:21:35
que si intentamos visualizarlo, more es un comando
01:21:38
de Linux que nos muestra sin editar los ficheros
01:21:42
si ponemos more persona.class, pues fijaros como
01:21:46
es bytecode, una vez el código ya compilado no se ve exactamente
01:21:49
el mismo código que tenemos aquí escrito. Entonces si nos venimos aquí
01:21:54
voy a comentar todo el código del main, ahí está
01:22:01
todo el código comentado, para que solo tener esto que ponemos, entonces si ponemos
01:22:16
aquí un system.out.println de rs
01:22:20
0, se llama inicio
01:22:26
fijaros, entonces el bytecode de la clase inicio.java
01:22:35
pues será inicio.class, llamamos a java, inicio
01:22:40
y me da un error, ahora os cuento el error, si yo pongo
01:22:43
inicio hola, fijaros como me muestra por pantalla hola
01:22:49
que he mostrado, la posición 0
01:22:53
del array RS, que se ha cargado en la posición 0 del array RS
01:22:57
se ha cargado este parámetro
01:23:01
que le he pasado cuando he llamado al programa, si yo pongo
01:23:05
java inicio hola adiós
01:23:09
y también muestro la posición 1 del array RS
01:23:15
que es, recordad, ars es un array de strings
01:23:22
salvo por aquí el programa para que me actualice el
01:23:26
bytecode, entonces fijaros como ya me muestra hola y adiós, este hola corresponde
01:23:32
a la posición 0 del array, esta
01:23:36
y este adiós corresponde a la posición 1, si yo ahora aquí, si yo hago
01:23:39
una ejecución en la que pongo esto, quitando el adiós
01:23:45
me muestra el hola, la posición 0 y me da
01:23:49
un error, que es cuando intenta acceder a la posición 1 del array
01:23:53
¿por qué no existe la posición 1? pues porque no le he pasado un segundo parámetro, esto ha cargado
01:23:57
en el arc S0 y en el arc S1 no ha cargado a nadie
01:24:01
que es lo que me había pasado aquí cuando hice un Java
01:24:04
inicio, porque hice este Java inicio
01:24:09
y me di un error intentando acceder a la posición 0 del programa
01:24:12
es decir, ¿en qué momento se llama el método
01:24:18
main, se llama el método main cuando intentamos arrancar el programa, que es el momento
01:24:25
cuando se ejecuta cualquier método, es el momento en el que
01:24:31
estas variables que tiene por aquí entre paréntesis se cargan con información
01:24:34
por aquí hemos cargado constructores con
01:24:39
información cuando hemos hecho la llamada al constructor, por aquí hemos
01:24:43
cargado con un string una variable del método saludar
01:24:47
el que está sobrecargado con un string cuando hemos hecho la llamada, en el momento que llamábamos
01:24:51
a ejecutar a saludar le pasamos por aquí el dato esto cuando se cargará pues se cargará en el
01:24:55
momento que llamemos al main pero es que el main no lo llamamos nosotros desde código sino que se
01:25:02
llama en el momento en el que lanzamos el programa como estamos haciendo por aquí si no queréis venir
01:25:05
para probar esto al terminar y lanzar el programa también ya lo vimos un día a ver si me acuerdo
01:25:12
estaba en como verás configuration saber era aquí si miras aquí para hacer esto mismo que
01:25:21
he hecho de pasarle parámetros a la ejecución del main a la ejecución del programa es decir
01:25:31
en la llamada al main parámetros que se cargan en ars 0 y en ars 1 para hacer esta simulación
01:25:37
desde Eclipse, pues nos podemos venir
01:25:43
aquí a la opción
01:25:45
de menú run
01:25:47
cobreis configurations
01:25:48
y aquí
01:25:51
aparece la opción arguments
01:25:53
entonces aquí en arguments
01:25:55
podemos poner los argumentos
01:25:57
este hola y adiós
01:26:01
corresponden justo
01:26:03
a este
01:26:05
hola y adiós que os he puesto
01:26:06
aquí, más allá de la llamada
01:26:09
entonces si yo digo aplicar
01:26:11
close si yo ahora hago una ejecución aquí de
01:26:15
eclipse fijaros como demuestra ese o la que es el que puesto ahí porque solamente
01:26:19
puesto ahora aquí el ars s les comento también este otro y me
01:26:23
saldría el ola y adiós este ola y adiós son estos dos argumentos que he puesto
01:26:29
aquí cambió por dos y ya me hice ola y dos bien entonces tenemos en el main
01:26:39
tenemos, en este caso es void, podría, main
01:26:54
tiene esta cabecera, es decir, es inamovible, tiene que ser
01:26:58
así, pero para cualquier otro método equivalente al void
01:27:02
podríamos tener un int, un string, un tipo referenciado
01:27:06
otro día lo volvemos a dar a lo mejor otra vuelta
01:27:10
luego está la etiqueta estática de aquí en el main, de esta os he hablado
01:27:13
también en diferentes tutorías, cuando cosas
01:27:18
se definen de forma estática, primero
01:27:22
os cuento sin el static. Cuando una clase
01:27:26
no es estática, pues tenemos
01:27:30
podemos definir diferentes objetos de esa clase
01:27:33
y el acceso, bueno, las cosas estáticas en líneas generales
01:27:38
es que con lo que mejor se entiende el término estático es con los parámetros.
01:27:42
Las cosas estáticas en líneas generales es que están compartidas
01:27:46
por todos los objetos de una clase
01:27:51
entonces si yo
01:27:53
el main
01:27:55
no era una clase, era un método
01:27:57
pero se entiende mejor para los
01:27:59
parámetros, si yo pongo aquí
01:28:01
un public, fijaros
01:28:03
static
01:28:04
y valor, vamos a poner
01:28:06
int
01:28:11
de tipo entero, fijaros
01:28:13
este static para este
01:28:18
valor lo que supone, voy a borrar por aquí
01:28:20
vamos a crear
01:28:24
una primera persona. Fijaros que aquí en la clase
01:28:26
de persona he mantenido la edad como un parámetro
01:28:47
de tipo entero que no es estático y valor lo he mantenido
01:28:51
como un tipo entero pero estático. Entonces yo pongo aquí miper
01:28:55
punto y valor igual a 15.
01:29:00
De fin, una segunda persona y para esta segunda persona
01:29:10
digo que tengo una edad 20 y el valor le voy a decir que sea 25.
01:29:14
y ahora pongo aquí un system out
01:29:20
.println
01:29:23
y vamos a poner estos dos datos
01:29:25
de mi per
01:29:29
voy a poner aquí unos espacios
01:29:30
y el segundo
01:29:36
de los datos
01:29:39
mi per y valor
01:29:40
y vamos a hacer lo mismo para la segunda
01:29:42
de las personas
01:29:51
entonces si yo ejecuto aquí
01:29:52
mira lo que pasa
01:29:57
en principio si nosotros vemos
01:29:59
que estamos mostrando aquí mi per, la edad y mi per, valor
01:30:05
lo que nos hace pensar es que la edad, si la hemos asignado a 10
01:30:09
nos va a mostrar un 10 y el valor nos va a mostrar un 15
01:30:13
pero esta primera línea nos dice que es 10 y 25
01:30:16
y en este segundo caso, mi per y edad y mi per y valor
01:30:19
pensamos que nos va a devolver 20 y 25
01:30:25
que efectivamente es correcto lo que hace, pero lo que nos chirría
01:30:28
un poco es aquí, porque aquí no nos muestra un 15, pues bueno, volvemos
01:30:33
a hablar un poco de lo que es las zonas de memoria, cuando
01:30:38
nosotros hacemos un new aquí para mi pair, si este tiene la posición
01:30:41
30.000, el reserva con el new espacios de memoria
01:30:46
para sus atributos, pero no se preocupa de aquellos atributos
01:30:50
que son estáticos, en este caso reservaría un espacio
01:30:55
de memoria a partir de la 30.000 para el ese nombre y la iedad
01:30:58
ese nombre e iedad. En este caso, para miper2
01:31:01
en la 40.000, reservaría para esa segunda persona
01:31:12
espacio para ese nombre y para la iedad, igualmente
01:31:18
y en forma global para todas las personas, no para esta
01:31:22
ni para esta otra, se fijaría en aquellos que son estáticos
01:31:26
y para la clase persona, pero no para un objeto en particular, sino en línea
01:31:30
en general, y de forma compartida, reservaría
01:31:34
espacio de memoria, vete a saber en qué posición
01:31:38
el sistema operativo, vamos a poner aquí la 80.000
01:31:42
para aquellos atributos que sean estáticos, que en este
01:31:45
caso es iValor. Y estos atributos, al ser
01:31:50
static, que podríamos decir que es igual
01:31:55
a compartidos, estos atributos tienen una única posición de memoria
01:31:59
para todos los objetos. Entonces cuando
01:32:05
yo asigno aquí a iedad el valor de 10
01:32:08
como iedad no es estático, se irá a su posición de memoria
01:32:12
aquí y cogerá y me pondrá un 10 aquí.
01:32:16
Cuando yo voy a mi per, que es una persona
01:32:23
y valor y le asigno un 15, fijaros como por ser
01:32:25
estático no hemos hecho reserva de memoria aquí, sino que se ha hecho para la persona en su conjunto.
01:32:29
Entonces cogerá y se vendrá aquí al ser estático y pondrá
01:32:33
un 15. Si yo ahora cojo y asigno
01:32:37
un 20 aquí, como iedad no es estático
01:32:44
y cada uno de los objetos tiene su zona de memoria
01:32:46
lo que nos hará es aquí en esta iedad
01:32:49
cogerá y pondrá un 20. Pero si yo
01:32:52
me voy aquí y asigno a iValor
01:32:57
que es un parámetro estático de la clase persona
01:32:59
el valor 25, como no tenemos
01:33:03
para cada uno de los objetos ese iValor, donde se irá
01:33:06
a la zona global de la clase
01:33:09
persona, entonces, que es esta
01:33:12
y que está compartida. Entonces, este
01:33:14
15 lo estará sobrescribiendo a 25.
01:33:16
Y perdemos
01:33:20
el 15 que habíamos puesto aquí.
01:33:20
Bueno, decimos, lo perdemos.
01:33:23
Bueno, es que a lo mejor es lo que nos interesa
01:33:24
según el enunciado del ejercicio.
01:33:26
Si todos tienen,
01:33:28
imaginaos que tienes,
01:33:31
vamos a hacer una exageración de dato,
01:33:32
pero un millón de personas que
01:33:34
todos pertenecen a
01:33:36
a Dan, vamos a decir,
01:33:38
a nuestra clase
01:33:40
de DAM. Todos ellos.
01:33:42
Y además un poco exagerado
01:33:45
con lo del millón de personas, pero bueno,
01:33:46
para que sea más ilustrativo.
01:33:48
Si tuviéramos que cambiar
01:33:50
el nombre de ese millón de personas, como
01:33:51
cada uno tiene su nombre, no nos quedaría más remedio
01:33:54
que ir uno a uno y cambiar su nombre.
01:33:56
Porque sería una variable de este tipo, de cada uno
01:33:58
de los objetos, de cada una de las instancias.
01:34:00
Pero si lo que queremos es
01:34:03
cambiar el que pertenece
01:34:04
en a DAM, porque ahora
01:34:06
desde la consejería de educación nos dicen que en lugar de
01:34:07
DAM sea DAN, pues sin necesidad
01:34:11
al ser un dato común a todos ellos de ir
01:34:15
a ese millón de objetos y hacer el cambio de DAM a DAN
01:34:17
como es común, pues iríamos a la variable estática
01:34:20
y con un único cambio quedarían automáticamente
01:34:23
todos actualizados, que es lo que nos ha sucedido aquí con
01:34:26
IVALOR. Como consecuencia de que
01:34:29
IVALOR, aquí pusimos 15 para mi PER
01:34:32
pero luego hemos puesto aquí 25
01:34:35
es actualizado, cuando aquí estoy mostrando y valor para mi per
01:34:37
como la zona es común, el dato que tiene es 25 y como consecuencia
01:34:41
nos muestra aquí este 25, entonces esta es la información de los datos
01:34:46
como funcionan los atributos que definimos
01:34:51
como estáticos, de igual forma los métodos también
01:34:55
pueden ser estáticos, en realidad cuando definimos
01:34:59
un objeto y ponemos un método como el de saludar
01:35:03
que no sea estático, lo que hace es
01:35:06
que cada uno de los objetos tendrá su propio método saludar
01:35:09
y si aquí ponemos static, como le sucede al main
01:35:14
pues será un método común para todos los objetos y llamará justo
01:35:17
la misma zona de código compartida entre todos
01:35:22
la misma idea que para los parámetros, lo que pasa es que con los parámetros el ejemplo
01:35:25
se ve muy claro haciendo una cosa así de este estilo
01:35:30
Pero si nosotros cogemos y ponemos aquí y edad igual a 45, ¿qué nos pasa? Que esto no nos compila. Y no nos compila, volvemos un poco a lo mismo que con la sobrecarga hablábamos de las ambigüedades.
01:35:32
si yo pongo aquí y edad, pensando en una persona
01:35:53
me dirá, muy bien, pero ¿qué persona, la edad
01:35:57
de qué persona quieres cambiar? Tú date cuenta que si es la edad del miper1
01:36:01
me tengo que ir a la posición que cuelga del 30.000 para cambiarlo. Y si es
01:36:04
de miper2, cuelga del 40.000. Entonces
01:36:08
como no seas más preciso, yo no te dejo compilar porque no es un
01:36:12
parámetro estático y no sé a quién tengo que cambiar. Entonces, si
01:36:16
yo cojo y pongo aquí mi per 2 punto y edad ya me compila porque ya no hay ambigüedades mi per 2
01:36:20
empieza en la posición 40.000 y la edad está aquí pues lo que estoy haciendo es cambiar este dato
01:36:28
a 45 cambio los datos estáticos me permiten hacerlos de esta forma poner en lugar de un
01:36:32
objeto persona punto fijaros cómo me ofrece el y valor para cambiarlo un dato que es estático
01:36:41
lo puedo cambiar a través de cualquiera de sus
01:36:50
objetos, aunque siempre van a actuar sobre la misma posición de memoria, el cambio va a ser
01:36:54
común a todos, o a través de la clase total, si solo tengo una posición
01:36:58
de memoria, no hay ambigüedades, de nuevo, pues te lo permito. Entonces, en este caso,
01:37:02
lo que me haría sería el 55. Pero fijaros cómo
01:37:06
a través de la clase persona, punto, no me da la opción
01:37:09
de cambiar una edad, porque me diría, no, eso no es un dato estático, no es común
01:37:17
a todas las personas, no tengo ni idea de qué persona
01:37:20
quieres cambiar la edad. En este ejercicio es miper y miper2
01:37:23
pero podrían ser muchos otros. Para acceder a
01:37:26
datos con independencia de los estáticos
01:37:34
de cualquier clase, necesitamos
01:37:37
definir un objeto. Para cambiar
01:37:40
la edad de una persona, obligatoriamente necesito
01:37:43
definir el objeto de la clase persona miper
01:37:46
y así de esta forma puedo acceder a él.
01:37:49
Siempre, por
01:37:53
Regla general, que queremos acceder a un parámetro o a un método de un objeto de una clase, tendremos que instanciar su clase.
01:37:55
¿Con qué excepción? Con la excepción de parámetros y métodos que sean estáticos.
01:38:02
Si son estáticos, puedo decir, lo defino para la clase y cuando vaya habiendo instancias de objetos de esa clase, ya tienen esos datos.
01:38:09
¿Dónde utilizamos nosotros continuamente métodos estáticos?
01:38:19
Pues mirad, un sitio donde utilizamos métodos estáticos es cuando ponemos el system.out.println.
01:38:23
Esto, fijaros que tiene toda la pinta de la sintaxis de los métodos de los que estamos hablando.
01:38:31
Tiene un nombre y recibe por aquí, tiene entre paréntesis, en particular el println recibe aquí una cadena de caracteres o cadenas de caracteres puede recibir.
01:38:36
O está sobrecargado con diferentes opciones.
01:38:49
esto pertenece, es un método que pertenecerá en la librería de Java
01:38:51
a una clase que es la clase System.out que es un flujo de salida hacia pantalla
01:38:57
hemos instanciado un objeto de System.out antes de llamar
01:39:01
al método println como necesitábamos para
01:39:05
escribir por ejemplo sobre el parámetro y edad, no, entonces
01:39:09
println como estará definido en la librería de Java
01:39:13
pues como un método, más punto, mirad el valor
01:39:17
absoluto de un número? Pues hay una clase que es la clase math
01:39:24
y hemos llamado al método valor absoluto
01:39:30
de un número que recibe aquí como parámetro. Si metemos un
01:39:35
valor que sea menos 5, pues nos devolverá un 5. Si metemos el 5, pues el 5,
01:39:38
el valor absoluto de matemáticas. ¿Hemos instanciado un objeto
01:39:42
de la clase math? No. ¿Hemos sido capaces de llamar a un método?
01:39:47
Sí. ¿Esto qué implica? Pues que implica que apps
01:39:50
en las librerías de Java, estaría definido como
01:39:54
un método estático. ¿Alguna duda? Yo creo que vamos a ir
01:39:58
cerrando ya aquí, porque son las 7 y cuarto.
01:40:08
Sí, más o menos bien. Mirad, del main, bueno, todavía la próxima clase
01:40:15
os sigo contando más. Me entra un eco, no sé si alguien habéis dejado abierto
01:40:20
el micro. Bueno, pues nada,
01:40:27
la próxima clase os cuento, os sigo contando cositas de esto.
01:40:33
termino con el main, que nos ha faltado
01:40:36
bueno, el main que es algo común a todos los métodos
01:40:39
pero aparece también aquí en el main, el public
01:40:43
y bueno, pues vamos haciendo por ahí
01:40:45
algunas cositas más, mientras tanto os voy viendo
01:40:47
por ahí por los foros, si tenéis alguna
01:40:51
duda y bueno, y poco más
01:40:54
que contaros, si
01:40:57
alguien tiene una pregunta por ahí, dime
01:41:03
- 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:
- 92
- Fecha:
- 2 de diciembre de 2024 - 19:23
- Visibilidad:
- Clave
- Centro:
- IES ALONSO DE AVELLANEDA
- Duración:
- 1h′ 41′ 37″
- Relación de aspecto:
- 1.78:1
- Resolución:
- 1920x1080 píxeles
- Tamaño:
- 200.59 MBytes