Nos habíamos quedado en la pregunta esta. Es una pregunta bastante tonta, trivial, pero si el string que devuelve esta función, este método, tiene incorporados dos saltos de línea, hay que tener en cuenta que el println, después de mostrar este string, también añadirá un salto de línea. Esta es la característica que añade ln. Tenéis que saber que existe, en caso de que lo necesitéis, la versión System.out.print sin el ln, que justamente lo que hace es no incorporar un salto de línea. Lo digo por si alguna vez lo queréis utilizar. Existe la versión así. Existen las dos funciones. Vamos a lo siguiente que íbamos a empezar, que era la sentencia if. La sentencia llamada condicional. Es la condicional por excelencia. Se utiliza simplemente en medio del código cuando necesito hacer una bifurcación. Incluyo la palabra if, abro un paréntesis y lo cierro. Esto en Java es obligatorio y otros lenguajes en los que no. Y aquí en medio incluyo una pregunta. Una pregunta en el sentido de una expresión booleana. ¿Qué es una expresión booleana? Si el nombre nos es familiar significa simplemente una expresión que al final concluya en una valoración verdadera o falsa. Por ejemplo, x es más grande que 5. Esta es una afirmación que puede ser verdadera o falsa en el transcurso de un programa. Pues de este estilo, x mayor o igual que 5, y menor que 7 o no sé cuántos. Podríamos hacer expresiones booleanas verdaderamente complejas y tomar decisiones sobre ellas. Luego, abro un bloque de código y lo cierro. Fijaos que al abrir y cerrar los bloques de código hay... Esto es una cuestión de estilo. Si preferís poner la apertura de la llave, a mí en general me gusta más en este lugar, es decir, al otro lado no hay ningún problema. Los espacios en blanco y los saltos de línea para el lenguaje Java son decorativos, es decir, tiene que haber unos mínimos, pero si aquí lo quieres poner a continuación o quieres saltar de línea depende también de tu forma de codificar, como queráis. Y luego tenemos la opción, porque esto es una opción, de utilizar la palabra else y definir el código a ejecutar en caso contrario. Digo opción porque yo podría hacer un if con sólo el bloque a ejecutar si se cumple esta condición y luego continuar. Sería algo así, es decir, gráficamente una forma de representar un if sería, si me imagino que el programa viene por aquí, llega un momento donde hay una pregunta, una expresión. Y el código se abre en dos ramas. Una rama si la respuesta es sí. Y una rama si la respuesta es no. ¿De acuerdo? Esto sería un if clásico aquí, un bloque de instrucciones y en el caso del sí, otro bloque de instrucciones. Cuando se han ejecutado el bloque A y el bloque B, el bloque de la izquierda, el que justamente he etiquetado como A, sería el correspondiente al else, el código se reúne y se continúa por un flujo único. Lo que pasa es que esta rama puede no existir. Mira, esto es lo que digo con lo que else es opcional. Entonces, ¿qué pasaría? Llego aquí, si la pregunta es verdadera, ejecuta un pedazo de código y si no, sigue adelante. Muy bien. Sigamos. Un ejemplo. Para un método insertar dinero que no devuelve nada y recibe una cierta cantidad. ¿Qué puedo hacer? Bueno, si me intentan insertar un dinero con una cantidad positiva, es decir, mayor que cero, Es correcto. Es decir, yo el saldo de mi cajero automático lo incremento en esta cierta cantidad. Pero si no, se trata de una entrada, un parámetro con un valor inválido. Y eso lo puedo detectar en este caso y en este caso mostrar un mensaje. ¿Qué pasa justo después de lo que acabo de explicar? Que un método con un sistema println es una limitación. Bueno, digamos, ¿queréis hacer una versión que respete el criterio que os había dado antes de no tener sistema println dentro de los métodos de vuestros objetos? De vuestras, sí, de vuestros objetos. Pues veamos, podríamos hacerlo de otra forma. ¿Qué alternativa si queréis seguir esta línea que os había dicho? Uy, o he saltado atrás o hay un error. Esta sería la versión mejorada. Hacer que esta función insertar dinero. devuelva un valor de verdadero o falso, un valor booleano. Eso es posible, es un tipo de datos como cualquier otro. Y el parámetro de entrada sea el mismo. Si la cantidad es positiva, funciona exactamente igual, pero retorno un valor verdadero. Este valor verdadero simplemente va a ser usado para, desde afuera, desde el programa principal, saber que todo ha ido bien. En cambio, si el valor es negativo, no muestro nada, pero devuelvo un valor, un valor falso. ¿Qué ventaja tiene esto? Que desde afuera, con esta información de que el insertar dinero ha ido mal, puedo hacer lo que quiera. En el ejemplo anterior, automáticamente la opción está predeterminada, mostraré un mensaje y punto. Pero si quiero además hacer un sonido de aviso al usuario, si quiero producir un sonido o reproducir un audio, mostrar un mensaje, una animación, esta forma de codificar es un poco más flexible de cara al programa principal. El programa principal puede... Puede tomar más decisiones que en el caso anterior, volveré atrás. En el que las decisiones están tomadas de antemano. Aquí. Aquí la decisión está tomada de antemano. Es mostrar un mensaje por consola. Más limitado. ¿De acuerdo? ¿Entendéis un poco por dónde van los tiros de esta pequeña mejora? Oye, de verdad que es una mejora marginal y un poco de estilo. Pero ya os digo, si la queréis incorporar, está un poco mejor. Bien. Hablamos de otro concepto. Variables locales. Hasta ahora hemos hablado de atributos, pero no habíamos presentado variables. Variables en las que almacenar valores temporales. Bueno, primera reflexión. Los atributos no son más que un tipo de variables. Lo que pasa es que van ligados al objeto. Y son distinguidas en este sentido. Almacenan valores durante toda la vida de este objeto. Y yo puedo referirme a esos atributos en cualquier método de la clase. Es decir, si tengo un atributo pvp. y hago un método muy complejo, siempre que escriba en ese método pvp estaré utilizando ese atributo. Pero además, en adición, muchas veces yo necesito valores auxiliares para almacenar cálculos intermedios, porque hago cosas complejas y necesito algo intermedio. Bueno, pues puedo definir variables locales. Se caracterizan porque van dentro de un método, es decir, en el ámbito de un método, y por supuesto se hubiera el más breve, porque solamente existen y se pueden usar cuando ese método se está ejecutando. Es decir, solo dentro del ámbito del cuerpo, es decir, entre la llave de abertura y la llave de cierre del método en el que se han definido. Aquí dentro sí me puedo referir a esta variable local, pero en otro método ya no, esa variable ya no existe. Eso quiere decir que en dos métodos puedo utilizar variables con el mismo nombre, porque no se ven, no se pisan entre ellas, pertenecen a ámbitos diferentes. ¿Vale? Y tienen esta función de almacenar valores auxiliares. Aquí tengo un pequeño ejemplo. Aquí tengo un método llamado getSaldo en el que defino una variable que solo va a ser accesible aquí dentro. ¿Qué característica tiene? Que no llevan ámbito de visibilidad. Llevan un tipo, por supuesto, y tienen un nombre. Pero no tienen ni public ni private aquí a la izquierda. ¿Por qué? Pues porque no lo necesitan. Sabemos que su vida está restringida a este ámbito. ¿Y con ello qué puedo hacer? Bueno, pues aquí guardar el valor anterior a la modificación y poner el saldo a cero. No sé si esta función tiene mucho sentido, pero es igual. GetSaldo pone el saldo actual a cero, pero retorna al usuario el saldo anterior. El saldo viejo. Sería como si vacías el cajero o algo así. ¿De acuerdo? Bueno, pues usa tantas variables locales como necesitéis en un método. Las definís ahí, bum, bum, bum, todas las que necesitéis para vuestros cálculos. Vale, hemos llegado al final de esta primera parte. La otra veremos si nos cunde el tiempo. Hemos hablado que el cuerpo de una clase contiene atributos, constructores y métodos. Los atributos son los que contienen el estado del objeto, los constructores inicializan y los métodos definen el comportamiento. Voy a ir un poco rápido. Tenemos atributos, parámetros y variables que todos son variables. Fijaos que todos están, digamos, en el saco de las variables. Los atributos viven durante toda la vida del objeto. Los parámetros los usamos para mandar o recibir, según se mire, información a un método o a un constructor, por supuesto. Sabéis que constructor es un caso especial de método. Y las variables locales almacenan valores a corto plazo, solo dentro de un método. Y por último, hemos visto la sentencia IF, cómo tomar decisiones, decisiones derecha e izquierda, verdadero o falso, ante una respuesta booleana. Tomar una de dos opciones alternativas. Veremos el resto de estructuras de control, no nos va a bastar con esto, pero bueno, ya tenemos para hacer código un poco más interesante. Metémonos en la segunda parte, objetos y cómo manejarlos. Aquí ha saltado una diapositiva. En este punto del tema se comentan dos conceptos de diseño de la programación orientada a objetos. Bueno, esto es un poco más filosófico, pero bueno, lo comentamos brevemente. Es muy común que la programación orientada a objetos busque el mecanismo de abstracción y modularización, lo hemos visto un poco. Precisamente modularización, empezaré por aquí porque me viene bien por el ejemplo que tengo en la cabeza, consiste en dividir un problema en partes bien definidas que pueden resolverse independientemente. A mi modo de ver, el método imprimir ticket o get ticket o el método este que en caso de intentar modificar el saldo no hace un sistema outprintln dentro, está mejor modularizado que otro. Es decir, es más modular en el sentido de que es una pieza más combinable con otras. ¿Entendéis? Es decir, dividir un problema en partes bien definidas. ¿Qué quiere decir bien definidas? Pues que la interface, o sea, la comunicación con el exterior es útil lo mejor posible. Fijaos que al principio decía que esto es lo mismo que diseñar un circuito o un mecanismo. Los coches hoy en día se fabrican de forma modular para que sobre la misma plataforma pueda construir diferentes carrocerías o diferentes equipamientos o niveles de equipamiento. La modularización es un concepto de ingeniería y en software también. Bueno, un comentario, ya os digo, un poco filosófico. Hasta acción. Es un mecanismo que la programación orientada a objetos ayuda un montón, es decir, me permite ignorar detalles de partes para enfocar la atención en una visión más general. ¿Por qué la programación orientada a objetos es buena? Pues porque, ya os he dicho al principio, yo puedo tener un objeto que hice hace cinco meses y está bien programado, pero puedo olvidarme de cómo lo hice por dentro y enfocar mi problema al nivel superior, es decir, tengo un objeto con un comportamiento explicado que sé que se va a comportar así y lo tengo probado y garantizado que funciona, pues entonces me olvido de él, lo uso y trabajo en otro nivel del problema. Bueno, esto en programación orientada a objetos es una gran ventaja. Bueno, estos conceptos en el libro... El tema tres, poner un proyecto de creación de un reloj digital y hablan de esto de una forma un poco más extensa. Si queréis un poco profundizar en este tema, pues está este apartado. Vale. Vamos a crear objetos. Os había dicho que podemos crear objetos y no tenemos que pensar en hacer clic en el diagrama de clases de BlueJ para crear objetos. No, los vamos a hacer en un programa. O sea, dinámicamente mi programa se pondrá en marcha y creará objetos. Vale. Pues vamos a hablar un poco de eso. ¿Desde dónde se crean objetos? Bueno, pues en el flujo del programa principal yo puedo invocar la creación de objetos. Os mostré un ejemplo. Volveremos sobre él. Perdona, tengo... Ah, pues ya está. Pero también... Bueno, aquí hay un pequeño rata. Una pequeña rata. En el constructor, cuando yo creo un objeto, puede ser que la creación de un objeto implique la creación de subobjetos. Es decir, yo puedo tener objetos compuestos de pequeños objetos en su interior. O sea, claro, los objetos... se combinan con otros para crear objetos más complejos. Bueno, pues típicamente cuando yo construyo un objeto es muy normal que dentro haya instrucciones de creación de otros. O bien desde un método cualquiera yo puedo invocar a, mira, necesito crear un objeto de tal clase. Sea como sea, se hace siempre del mismo modo. Tú defines una variable de la clase del objeto que vas a crear. Esto, hasta aquí, hasta este punto, todavía no ha creado el objeto. Simplemente ha previsto una variable para tenerlo enganchado. Y luego es el comando new llamando al constructor, pasándole los parámetros del constructor que te interesa o los que pida tu constructor, el que se encargará de la verdadera construcción del objeto. Y te devuelve un valor de una referencia a un objeto que tú almacenas aquí. Esta instrucción a veces la puedes escribir en una sola línea. Es decir, podrías escribir class variable y antes del punto y coma aquí poner igual y hacer el new. A veces lo veréis escrito así. Es decir, en una sola línea también es válido. Es una cuestión de hacerlo más compacto o hacerlo en dos. No tiene ninguna diferencia. Y aquí tenéis este programa principal que os había dicho antes. En un programa principal creo dos variables de la clase componente y con dos news creo dos objetos. Como si quisiera crear treinta. Como si quisiera, no va a ser el caso, iniciar un diálogo con el usuario y en función de lo que me diga el usuario en una especie de iteración crear los objetos en función de las demandas del usuario. Puede ser más interactivo. Aquí está fijo por código que siempre que ejecute este programa crearé dos objetos. Pero podría ser una cantidad variable dependiendo de la interacción con un usuario o con otro sistema. Vale. Hay una cosa a tener clara. Tenemos toda la batería de tipos primitivos. Int, float, boolean, char, string... También tenemos que entender que nuestros objetos se incorporan a los tipos disponibles. Por eso es por lo que me refiero aquí como tipo objeto. Es decir, cuando yo he creado una clase, puedo crear variables capaces de almacenar referencias a objetos. Pero tiene una gran diferencia. Así como una variable i de tipo int almacena directamente el valor, cuando yo defino una variable de tipo componente y la llamo c1, no estoy creando el objeto, sino que lo que estoy creando es una variable capaz de mantener lo que se llama una referencia a un objeto o un apuntador en otros lenguajes, o un puntero a un objeto. Realmente lo que guardaré en c1 es... Algo... Que quien va a crear este algo es el comando new. Quien crea este objeto es new. Y este objeto almacenará en sus atributos, sus valores y todo lo que sea. Si esto es un tipo de componente, pues tendrá código, precio y venta al público, etc. A la luz de esto, un pequeño ejercicio. Otra vez. Sí, es que duplico diapositivas por un pequeño error de tecleo. Ejercicio. A ver. Primero, mirad este código que termina con un sistema .println y luego el código siguiente que termina con otro sistema .println. Tienen un fuerte paralelismo, es decir, hacen aparentemente algo muy parecido. Solo que uno trabaja con int a y b y el siguiente código trabaja con a y b dos variables del tipo componente. Que se supone que es un objeto de una clase, bueno perdón, que componente es una clase que he creado. Aquí. La variable a le asigno el valor 32. A la variable b le asigno el valor que tiene a, y a la variable a le sumo 1. Es decir, la variable a aparentemente tendrá un 33. Si yo pido sistema oprintele n b, podéis escribir en un momento rápido qué saldrá por pantalla si pido mostrar el valor de b. Es bastante evidente, pero efectivamente, 32. Eso es. Lo importante es ver el paralelismo. Aquí tengo dos variables de tipo componente, creo un objeto componente vacío, y utilizando un método set le pongo un nombre de fabricante. Digo que este componente lo fabricó la compañía AMD. Justo después, con la variable b, capturo lo que hay en la variable a. Y después, a la variable a le hago un cambio. Cambio. Es algo parecido aquí. A la variable a también le hacía un cambio. Y le cambio a Intel. Si antes tenía MD, ahora le cambio a Intel. Fijaos que hago asset nombre fabricante MD, apunto ese nombre fabricante Intel. ¿Qué sucederá si yo aquí hago un sistema println de b getNomFabricante? Suponiendo que esto es un método que evidentemente consulta el atributo nombre del fabricante. ¿Qué saldrá? ¿Intel o AMD? ¿Qué pensáis? Bueno, yo tengo una respuesta. Alguien se quiere mojar. Porque tenemos a un compañero que opina que AMD sería un comportamiento simétrico a lo que ha sucedido en el ejemplo anterior. Va, os lo desvelo yo. En este caso... Muy bien. Vale, pues ya tenemos discrepancia. En este caso tengo que dar... La razón al segundo comentario. Sí, es Intel. ¿Por qué? Lo veréis gráficamente si entendéis lo que os explicaba antes. Paso de diapositiva donde tengo un ejemplo. Lo que ha sucedido es que cuando he hecho A igual a B, la variable A y la variable B han ido a apuntar al mismo objeto. Y es en este mismo objeto que antes tenía AMD, después le he cambiado a Intel y ahora le pido a través del objeto B. Oye, ¿cuál es el nombre del fabricante? Pues dirá Intel, lo último cambiado. En el ejemplo anterior... ...el hacer B igual a A. A y B son dos cajas separadas, independientes. Es decir, este puede tener un 33 y el otro un 32 y no están vinculados. Lo que sucede con A y B en las referencias a objetos es que no almacenan al objeto en sí, sino que almacenan una apuntadora al objeto, es decir, una referencia. Vuelvo al código anterior. O sea, guardando este dibujo en la mente es importante entender eso. Porque lo que está sucediendo aquí es, yo creo un solo objeto. Fijaos que solo hay un new. Y lo referencio con la variable a. A través de la variable a le cambio el nombre. Y luego hago que la variable b apunte al mismo objeto que está apuntando a. Esto es lo que hace esto. Apunta al mismo objeto que está apuntando a. Si al objeto al que está apuntando a lo cambio a intel, hay un solo objeto. Y aunque yo muestre el nombre del fabricante a través de la variable b, las dos están apuntando al mismo lugar. ¿Entendéis esto? Es bastante importante. ¿Sí? ¿Puedo seguir? Porque esto sí que me interesa. Vale, perfecto. Muy bien. Pues para eso estamos aquí. Para descubrir cosas nuevas, mojarse y cometer errores para aprender. Perfecto. No os cortéis. Está genial. intervenir y decir no es necesario acertar siempre además los ejemplos están puestos con mala leche a propósito, ya sabéis bueno, un pequeño ejemplo un ejemplo un poco tonto he imaginado una clase colegio es para mostrar un ejemplo como desde un constructor también se puede crear objetos imaginaos que la clase colegio solo tiene dos atributos uno que es string nombre el nombre del colegio esto sería una variable elemental y una variable de tipo objeto supuestamente de una clase llamada persona para tener el director es decir, un colegio se caracteriza así como está diseñado este con un nombre y con una referencia a una persona directora vale, pues en el constructor si el constructor recibe dos parámetros como el nombre del colegio y el nombre del director dentro del constructor, bueno haré lo básico, vale, muy bien el parámetro nombre lo almaceno dentro del atributo nombre que es una cadena pero para obtener algo dentro de la variable director lo que tengo que hacer es crear un nuevo objeto director porque no existe si me imagino que tengo un objeto de persona capaz de ser llamado solo con un string de nombre de persona eso lo construye y el atributo director almacena una referencia a este objeto o sea, al construir estoy creando un subobjeto a la vez, es un objeto colegio, colegio compuesto internamente por una referencia a otro objeto director y van juntos, bueno es un ejemplo solo para mostraros que en realidad lo que estamos haciendo ahora es aprender los ladrillos básicos y luego los puedes utilizar para montar el castillo que te dé la gana así como hemos hablado de un if El comando if, que tú puedes bifurcar a la derecha y a la izquierda. A la derecha puede haber otra bifurcación, por supuesto. Y al final tener un castillo sobre otro. Y esto, ¿qué límite de profundidad hay? Ninguno. Es decir, un if dentro de otro if, por supuesto. Y en esta rama, pues también. Pues lo mismo con la acumulación de colegios, de objetos. Es decir, puedo hacer objetos con objetos y objetos con objetos que tienen objetos. Todos los niveles que necesite mi lógica. Gráficamente, si queréis una representación, lo que sucede es que el objeto colegio, a ver si lo puedo dibujar a pesar de la precariedad de los medios. Yo creo un objeto colegio que está vinculado a la variable c1. Si ejecuto este código, perdón. Es decir, creo una variable c1 y después c1. es rellenada con lo que devuelve el comando new colegio, que lo que hace el comando new colegio es crear el objeto colegio en sí. Que dentro un objeto colegio tiene un atributo que es San José, aquí dentro iría escrito el nombre del colegio, y otro atributo que no contiene el valor. Lo que contiene este atributo es también una referencia a un objeto que se crea en el constructor que sería un objeto persona, inicializado con este nombre joanribot. De acuerdo, entonces esto sería el castillo que se monta simplemente con un crear new colegio y pasándole dos parámetros. Este segundo parámetro se usa para crear un segundo subobjeto interior. Vale, pues sería algo así. A esta diapositiva está de más, no os preocupéis por ella. Caramba, tengo que hacer bastantes correcciones. Vale, la valor null. ¿Null qué es? Bueno, es un valor especial en Java. Los atributos de un objeto, si tú no los inicializas a nada, están a null y es un valor distinguido. Es como el conjunto vacío, es una forma de formalizar el vacío que en lógica es muy útil muchas veces. Entonces, tú puedes utilizar este valor y preguntar por él. Es decir, puedes hacer un if que pregunte si la variable c1 contiene null. Fijaos que la comparación de igualdad es un doble igual. Esto es para distinguirla del operador de asignación. Este es un operador de asignación, esta es una variable y este es un valor null. Es decir, tú puedes decir que una variable capaz de apuntar a un director, de repente te quieres olvidar de la referencia. Este objeto y quieres ponerla a cero, es decir, que no apunte a nada. Es como si esta variable... que antes estaba apuntando a un determinado sitio, cambio de color, la cancelas, está apuntando a un objeto, se supone. Ahora lo que mantiene ahí dentro es un apuntador a tierra, a nada, un apuntador vacío. Esto sería un poco la representación de Null, un apuntador a nada. Ya veréis, más adelante nos puede salir a la utilidad. Ya hemos visto esto del ámbito de visibilidad. Ha aparecido en los atributos y en los métodos. Recapitulemos un poco. ¿Qué marcaremos con el ámbito de visibilidad public? En principio, para nosotros, lo restringiremos a los métodos. Pero no todos. Son los métodos que el objeto ofrece a otros objetos. Es decir, si mi objeto se va a comunicar con el exterior, será a través de métodos públicos. Private lo utilizaremos para atributos, y sabéis que no es obligatorio, pero es una gran recomendación, es decir, que nadie, por favor, haga atributos públicos. Pero también, si yo hago un método y lo marco como private, esto no está mal. Lo que pasa es que este método solo se podrá acceder desde otros métodos del mismo objeto. No son métodos para comunicarse con el exterior, son métodos, digamos, de gestión interna. Eso puede ser muy útil. No sé si he preparado un ejemplo, ya no me acuerdo. Pero, digamos, es, si tú vas a hacer una acción repetidas veces en muchos métodos, te conviene hacer un método privado propio para utilizarlo en varios sitios, pero ese método privado simplemente agrupa código, no es para que nadie lo use desde fuera. Vale, pues puedes hacer un método private. Eso no hay ningún problema. No rompes ninguna regla de oro. Este ejemplo viene del ejemplo del reloj. Tiene poco sentido. No sé cómo se me ha colado aquí. Pero bueno, veis, crean un método private void update display. Es algo para uso interno. ¿De acuerdo? Bueno, pues tú puedes hacer un método así si lo necesitas. ¿Cómo llamo a un método interno? Bueno, al fin y al cabo, los métodos internos, como tú los estás llamando desde dentro de tu objeto, simplemente te refieres a él por el nombre. Nombre, nombre, abres paréntesis, si necesitas parámetros, pones parámetros, cierras paréntesis, punto y coma. Eso sería para métodos definidos de este tipo. Private, no sé cuántos, un cierto tipo, que puede ser void o no, el nombre del método y sus parámetros. Para métodos públicos, si tú los vas a llamar desde el exterior, vas a tener que anteponer la referencia al objeto. Es como antes que yo he hecho C1... Punto. GetTicket. Vale. Pues eso es llamar a un método público desde fuera. GetTicket. Bueno, escribir así es terrible. Vale. Bueno, pues siempre desde fuera de un objeto yo puedo referirme a un método de este objeto con este prefijo. Tal objeto punto su método público. ¿De acuerdo? Para referirme internamente a métodos públicos también puedo hacerlo sin poner el nombre del método. Es decir, si yo tengo un método público internamente lo puedo llamar de esta forma. ¿Qué quiere decir? Es que si no pones el nombre del objeto queda sobreentendido. Que te está refiriendo a un método del propio objeto. Bueno, no quería liaros con esto, pero bueno, lo veréis. Quedaos un poco con esta forma de llamar a los métodos. En principio, si es desde fuera, te pones el nombre del objeto. Y si es desde dentro, no necesitas poner el nombre del objeto. Recapitulación final, final. Hemos hablado de la definición de clases. Y aquí hemos hablado de sus piezas, atributos, constructores y métodos. Y hemos visto que métodos, tenemos métodos del estilo get, del estilo set. Y otros que no son típicamente ni get ni set, sino son métodos complejos que hacen otras cosas. Get y set no son más que formas de referirse a los métodos más elementales. Hemos hablado de lo que son parámetros y lo que son variables. Hemos hablado de la instrucción de asignación, el igual. Y hemos hablado del if, la instrucción condicional variable. Clásica. Hemos hablado de lo que es la sobrecarga y sabemos que se aplica tanto a métodos como a constructores, pero también a operadores. Y hemos hablado también de variables locales. Tal vez no lo hemos hecho en este orden, pero es un poco el contenido del que hemos hablado en esta primera parte. Bueno, en la segunda hemos presentado los conceptos estos de adaptación y modularización. Hemos visto cómo creamos objetos, bien desde el programa principal, desde los constructores o desde cualquier otro método. Hemos visto la diferencia, esta es importante, ojo con esto. Es el ejemplo que hace referencia a cómo de diferente se comporta operar con números enteros o operar con referencias a objetos. Y hemos hablado de... ...de los ámbitos privado y public y cuándo los usaremos. No son los únicos, hay otro ámbito que se utiliza en Java que es Protected. Pero, si cabe, lo mencionaremos. Puede ser que en algún ejemplo utilicemos esto, pero será más adelante. Nos hemos autolimitado a hablar de estos dos ámbitos, privado y público, y tiene un significado bien claro y bien definido. Y finalmente hemos visto cómo llamar a otros métodos, tanto internos como externos. Antes de abrir un turno de dudas, unos pequeños recordatorios. Esto sería un poco, si queréis seguir al día la asignatura, lo que vamos a trabajar en la próxima tutoría. Me he dado cuenta que hay también un error en el plan tutorial, pero aquí está escrito con ciencia. Mirad el capítulo 4 y los apartados 5.1, 5.5, 5.11 y 5.13 del libro. Por supuesto que si os miráis todo el apartado 5 y os apetece, mejor que mejor, pero bueno, esto, digamos, nos lleva más al grano. Y la recomendación del equipo docente es pegarle un vistazo al apéndice I del libro base, del libro de BlueJ. Aquí os recuerdo que la próxima tutoría es el 20 de marzo y después traemos el sábado esta pequeña maratón de 4 horas. El sábado intentará no avanzar contenidos, sino tomar tiempo para repasar lo visto y trabajar más a fondo directamente sobre las cuestiones de la práctica. Pero tenemos estas dos sesiones seguidas, es decir, tenemos este jueves no, el siguiente creo que es, si no me equivoco, y después justo el sábado después de 9 a 1. Para la práctica, si habéis entendido... Si habéis entendido lo que hemos estado mirando y habéis empezado a mirar, seguramente la etapa 1, si no está terminada, está cerca de estar terminada. A lo mejor hoy os ha dado alguna pista que os apetece hacer alguna modificación. Pero vaya, la parte 1 es muy básica. La etapa 2 empieza el tomate. Empezar a mirarla y empezar a mirar en qué consiste la documentación del código. Para eso el apéndice I del libro base. Documentar el código no es sólo meter entre medias estoy haciendo esto, sino también hacer unas cabeceras antes de cada método. Sí, antes de cada método. Porque si las haces adecuadamente, tal y como te explica el apéndice I, vas a poder generar una especie de documentación de forma automática con Java. Entonces eso nos será muy útil. En la segunda parte, en esta segunda etapa de la práctica, vais a ver que nos van a pedir crear un objeto. Si no me equivoco es el objeto carrito de la compra. Que uno de sus componentes de ese objeto va a ser un objeto más complejo, que es un objeto de tipo lista. El objeto de tipo lista no lo tenéis que crear vosotros. Existen listas ya disponibles en las librerías estándar de Java. Y entonces vamos a usar estas librerías para que un objeto pueda tener enganchados debajo de sí un número variable de otros. La idea es que un carrito de la compra consistirá en una lista de componentes. Componente 1, componente 2, componente 3, componente 4. O sea, tengo un objeto capaz de almacenar una cantidad variable de otros objetos. Esta es el sentido del objeto lista. Y esto es la estrella del apartado 2 de la práctica. Si lleváis la práctica al día, recordad que esto sí está bien definido. Tenéis la opción de, antes del 28 de marzo, hacerme entrega de la etapa 1 de la práctica. Pero fijaos que antes del 28 de marzo tenemos estas dos tutorías. Tenemos otra tutoría como la de hoy y la de 4 horas del sábado. Las de 4 horas del sábado... Es mucho tiempo, lo sé. Tendremos que hacer varias pausas. Yo no estaré rajando todo el tiempo como ahora, sino que intentaremos hacer algo un poco más interactivo. Intentad para este sábado tener trabajo hecho que os haya generado dudas. Así le daremos sentido a estas cuatro horas de trabajo. Y después tenéis más que tiempo de sobra para entregar esta primera etapa. Recordad que si podéis cumplir los plazos intermedios tendréis hasta un punto extra de gratificación en la nota final de la práctica. No es mucho, pero es una forma de reconocer el que puede seguir la asignatura al día y además será mejor para vosotros. Vale, pues hasta aquí un poco lo que tenía previsto para hoy. Ha sido bastante denso, pero al final... ...hemos conseguido hacer. Estoy consciente que algunas cosas hemos ido rápido. ¿Algún comentario? A ver, si alguien quiere tomar la palabra le doy la voz o si queréis plantearme alguna duda. Hoy hemos hablado de muchas cosas y afortunadamente tenemos un poco de tiempo para discutir. Si queréis por el chat y si queréis hablar con el micro y eso, pues con el micro, no hay problema. ¿Dudas, dificultades, inquietudes, preocupaciones? Sobre todo a partir de lo visto hoy. Cosas que haya explicado regular y que no hayáis entendido bien o no sé. A ver, ah mira, se me ocurre una idea. Una cosa que sí podemos hacer ahora, si no hay dudas concretas. Voy a poner en marcha esta opción de compartir el escritorio, que probablemente decale el audio y el vídeo. Pero sí que voy a poder mostraros BlueJ y algunas cosas que no os he podido mostrar durante la presentación de las diapositivas. Vale, pues a ver si nos funciona bien. Voy a pausar el vídeo para no consumir ancho de banda con el vídeo y mantendré el audio en marcha. Y ahora está inicializando esto de compartir el escritorio. Muy bien. Bueno, en teoría esto sería como se vería vuestro proyecto al final de la etapa 1. Tendríais una clase componente. Y una clase lanzador que contiene el programa principal. ¿Qué os puedo decir de esto? Lo que os quería enseñar al principio es que cuando uno tiene creadas las clases y han compilado correctamente, si haces clic con el botón derecho sobre una clase, tienes la posibilidad de llamar a su constructor mediante el comando new. Con esto yo puedo crear un nuevo objeto componente. De esta forma, me pide un nombre, lo puedo llamar componente1, y aquí abajo, en rojo, aparece en el banco de objetos este primer objeto que he creado, de la clase componente. La clase lanzador... Si hago botón derecho, sí que puedo crear un objeto lanzador, pero no tiene sentido. Es decir, lo que sí tiene sentido en este objeto lanzador es este método main y ejecutarlo directamente. Es decir, la clase lanzador no está pensada para crear objetos a partir de ella, sino simplemente para ejecutar este método estático, que es un método que no depende de ningún objeto, sino es un método vinculado a la clase. No necesito tener objetos para ejecutar este método. En cambio, este C1 recién creado es un objeto de la clase componente y si hago botón derecho sobre él, sí que tengo a mi disposición todos los métodos que me ofrece. Es decir, yo puedo consultar su código de fabricante, puedo consultar su código, su descripción, etc. ¿Qué pasa si, por ejemplo, le pido cuál es el nombre del fabricante de un objeto recién creado? Pues que me devolverá... ¿Dónde estás? Ahí está. ¡Nom! No nos debería sorprender, es decir, ¿cuál es el nombre del fabricante? Null, porque no lo he inicializado. Fijaos que además, como me tomé la molestia de hacer en mi código lo que os decía, esta cabecera, aquí me está mostrando una información relativa a este método. Está diciendo, este es un método de consulta del valor del nombre del fabricante, arroba return, lo que retorna a este método es el nombre del fabricante del objeto. ¿Qué puedo hacer? Bueno, pues utilizaré uno de estos métodos set, set nombre del fabricante, para establecer a mano, a través del inspector de objetos, un nombre del fabricante. Lo tengo que poner entre comillas porque está esperando un string. Llamaremos a esto gigabyte, ¿vale? Muy bien, este es el nombre de un fabricante. Perfecto. Ok. A continuación, si sobre este objeto, por supuesto, le pido, dame el string del nombre del fabricante. Él me contestará. me devuelve lo que estaba esperando y así con la creación de todos los objetos que quiera puedo definir un segundo objeto a partir de la misma clase objeto componente 2, lo llamo EC2 y aquí por supuesto tener otros valores hacer nombre de fabricante aquí en este otro objeto AMD pues entonces ahora el objeto 2 está marcado como que pertenece al fabricante AMD y el otro a Gigabyte, EC1 no ha cambiado que el nombre de fabricante seguirá igual Gigabyte, mientras que si le pido a EC2 me va a devolver AMD a mi mano de web así como lo he hecho hasta ahora mi Mi constructor de componente es un poco pobre. Es decir, hacer un constructor que permite crear objetos componente completamente vacíos, ¿qué queréis que os diga? Tener que darle todos los valores uno por uno, set a set. Tal vez no estaría de más crear un constructor que recibiera en la propia línea del constructor unos cuantos parámetros. No sé si todos, pero podríamos hacerlo todo. ¿Cómo haríamos? Bueno, pues yo puedo editar este código, voy al constructor y en lugar de tener un constructor tan tonto como este, de momento tengo un constructor que simplemente dice public componente y dentro no hace nada, pues pasarle una serie de parámetros. Por ejemplo, un string con el parámetro nombre de fabricante. Y para simplificar, no los pondré todos para ir un poco más rápido, un entero con el código del producto. P minúscula, código. Bien, pues aquí dentro haré lo que se espera que haga. Voy a poner en el atributo nonfabricante lo que el usuario me pasa por parámetro, p nonfabricante. Y en código lo que el usuario me pasa como parámetro, p código. Con esto terminaré. Lo que hago es, bueno, compilo esta nueva clase. Aquí que es lo que no he escrito bien. Fijaos que dice no puedo encontrar el símbolo de no fabricante. Sí, hay una falta de coincidencia entre las mayúsculas. Ya lo habíamos comentado pero se me ha pasado. Perfecto, ahora está bien. Y ahora lo que sucederá es una vez compilado todo, puedo ir aquí a editar, compilar. Esto ejecuta la compilación de todo. Ah, claro, me está fallando porque ahora estos dos constructores no existen. No tengo un constructor vacío. Bueno, vamos otra vez a la clase componente. Como hemos dicho que puedo tener más de un constructor, voy a volver a construir un constructor vacío. Un public componente. Simplemente para no tener que modificar el código del programa principal, voy a crear este constructor vacío. Y ahora tengo dos constructores, uno que recibe dos parámetros y otro que no recibe ninguno. Este en principio no me gusta, después lo quitaría, pero es para no modificar el resto. Compilo, ahora todo compilado sin problemas, porque en el programa principal hay una referencia al constructor vacío, pero yo aquí en componente cuando hago botón derecho no utilizo el constructor vacío, sino utilizo el constructor que me va a pedir dos datos. De esta forma, al construir un objeto le doy un nombre, c1, pero le doy un nombre del fabricante, amd, y un código de producto que es un número, 123. Así, en el momento, nada más crear el objeto, este objeto, voy a utilizar esta opción inspect, me permite ver que interiormente el objeto ya ha sido creado recibiendo amd y 123 en sus atributos. Bueno, pues esto es un poco lo que nos ofrece BlueJ y su entorno este. Paro la presentación, paro la grabación y dejo de mostrar el escritorio simplemente para despedirme y daros las gracias por vuestra participación. La verdad es muchísimo más agradable poder tener un pequeño intercambio con vosotros. Muchas gracias, lo escribo por aquí y nos vemos en la próxima tutoría. De acuerdo, os recuerdo que estoy en los foros a vuestra disposición. Preguntad todo lo que queráis. Un saludo.