Prog Unidad 03
Prog Unidad 03
id=3383
Utilización de objetos.
Caso práctico
Ada y Juan se han reunido para discutir sobre distintos proyectos de BK
Programación. Ada le comenta a Juan que están teniendo algunos problemas
con algunos de estos proyectos. A menudo surgen modificaciones o mejoras en
el software en el ámbito de los contratos de mantenimiento que tienen suscritos
con los clientes, y realizar las modificaciones en los programas está suponiendo
en muchos casos modificar el programa casi en su totalidad.
En reuniones anteriores se ha comentado la posibilidad de aumentar el precio del contrato de mantenimiento de los
clientes. Se ha consultado con el equipo de comerciales y a regañadientes han aceptado un aumento que aún está por
decidir, pero aún así quizás no sea suficiente. La empresa necesita mejorar el método de trabajo para reducir
costes de mantenimiento del software y alcanzar la rentabilidad deseada.
[Link] 1/65
25/12/2018 [Link]
1.- Introducción.
Si nos paramos a observar el mundo que nos rodea, podemos apreciar que casi todo está formado
por objetos.
Existen coches, edificios, sillas, mesas, semáforos, ascensores e incluso personas o animales. Todos
ellos pueden ser considerados objetos, con una serie de características y comportamientos. Por
ejemplo, existen coches de diferentes marcas, colores, etc. y pueden acelerar, frenar, girar, etc., o las
personas tenemos diferente color de pelo, ojos, altura y peso y podemos nacer, crecer, comer, dormir,
etc.
Los programas son el resultado de la búsqueda y obtención de una solución para un problema
del mundo real. Pero ¿en qué medida los programas están organizados de la misma manera que el JoshuaDavisPhotography
La respuesta es que muchas veces los programas se ajustan más a los términos del sistema en el que se ejecutarán que a los del
propio problema.
Si redactamos los programas utilizando los mismos términos de nuestro mundo real, es decir, utilizando objetos, y no los términos del
sistema o computadora donde se vaya a ejecutar, conseguiremos que éstos sean más legibles y, por tanto, más fáciles de
desarrollar, modificar y mantener, y por tanto, menos costosos.
Esto es precisamente lo que pretende la Programación Orientada a Objetos (POO), en inglés OOP (Object Oriented
Programming), establecer una serie de técnicas que permitan trasladar los problemas del mundo real a nuestro sistema informático.
Ahora que ya conocemos la sintaxis básica de Java, es el momento de comenzar a utilizar las características orientadas a objetos de
este lenguaje, y estudiar los conceptos fundamentales de este modelo de programación.
Autoevaluación
Rellena cada hueco con la palabra más adecuada.
La Programación Orientada a Objetos pretende establecer una serie de técnicas que permitan trasladar los
problemas del mundo real a nuestro sistema informático .
Reiniciar Mostrar las respuestas
Su puntuación es 5/5.
[Link] 2/65
25/12/2018 [Link]
Caso práctico
Juan cuenta con la ayuda de María para desarrollar la aplicación para la Clínica
Veterinaria. Lo normal es pensar en tener una aplicación de escritorio para las altas y
bajas de clientes y la gestión de mascotas, y una parte web para que la clínica pueda
estar presente en Internet, e incluso, realizar la venta on-line de sus productos. María
tiene bastante experiencia en administración de páginas web, pero para estar
capacitada en el desarrollo de aplicaciones en Java, necesita adquirir conocimientos
adicionales.
Juan le explica que tienen que utilizar un método de programación que les ayude a
organizar los programas, a trabajar en equipo de forma que si uno de ellos tiene que
Ryan O'Connell
dejar una parte para que se encargue el otro, que éste lo pueda retomar con el mínimo esfuerzo. Nadie del equipo
debe ser imprescindible para que el trabajo continúe. Además, interesa poder reutilizar todo el código que vayan
creando, para ir más rápido a la hora de programar. Juan le explica que si consiguen adoptar ese método de trabajo,
no sólo redundará en una mejor organización para ellos, sino que ayudará a que las modificaciones en los programas
sean más llevaderas de lo que lo están siendo ahora.
María asiente ante las explicaciones de Juan, e intuye que todo lo entenderá mejor conforme vaya conociendo los
conceptos de Programación Orientada a Objetos.
De lo que realmente se trata es de que BK Programación invierta el menor tiempo posible en los proyectos que
realice, aprovechando material elaborado con el esfuerzo ya realizado en otras aplicaciones.
Dentro de las distintas formas de hacer las cosas en programación, distinguimos dos paradigmas
fundamentales:
Si nos damos cuenta, esta serie de acciones o pasos diferenciados no son otra cosa que verbos; por ejemplo el verbo pedir, calcular,
mostrar, etc.
Sin embargo, la Programación Orientada a Objetos aplica de otra forma diferente la técnica de programación divide y
vencerás. Este paradigma surge en un intento de salvar las dificultades que, de forma consustancial, posee el software. Para ello lo
que hace es descomponer, en lugar de acciones, en objetos. El principal objetivo sigue siendo descomponer el problema en
problemas más pequeños, que sean fáciles de manejar y mantener, fijándonos en cuál es el escenario del problema e intentando
reflejarlo en nuestro programa. O sea, se trata de trasladar la visión del mundo real a nuestros programas. Por este motivo se dice
que la Programación Orientada a Objetos aborda los problemas de una forma más natural, entendiendo como natural que está
más en contacto con el mundo que nos rodea, que es más cercana a nuestra forma de analizar, entender y resolver los problemas.
La Programación Orientada a Objetos es un sistema o conjunto de reglas que nos ayudan a descomponer la aplicación en
objetos. A menudo se trata de representar las entidades y objetos que nos encontramos en el mundo real mediante
componentes de una aplicación. Es decir, debemos establecer una correspondencia directa entre el espacio del problema y
el espacio de la solución.
[Link] 3/65
25/12/2018 [Link]
Pero, ¿qué quiere decir esto en la práctica?
Pues que a la hora de escribir un programa, nos fijaremos en los objetos involucrados, sus características comunes y las acciones
que pueden realizar. Una vez localizados los objetos que intervienen en el problema real (espacio del problema), los tendremos que
trasladar al programa informático (espacio de la solución). Con este planteamiento, la solución a un problema dado se convierte en
una tarea sencilla y bien organizada.
Autoevaluación
Relaciona el término con su definición, escribiendo el número asociado a la definición en el hueco
correspondiente.
Ejercicio de relacionar
Paradigma Relación Definición
[Link] 4/65
25/12/2018 [Link]
2.1.- Conceptos.
Para entender mejor la filosofía de orientación a objetos veamos algunas características que la diferencian de las técnicas de
programación tradicional.
En la Programación Estructurada, el programa estaba compuesto por un conjunto de datos y funciones "globales". El término
global significaba que eran accesibles por todo el programa, pudiendo ser llamados en cualquier ubicación de la aplicación. Dentro
de las funciones se situaban las instrucciones del programa que manipulaban los datos. Funciones y datos se encontraban
separados y totalmente independientes. Esto ocasionaba dos problemas principales:
Los programas se creaban y estructuraban de acuerdo con la arquitectura de la computadora donde se tenían que ejecutar.
Al estar separados los datos de las funciones, éstos eran visibles en toda la aplicación. Ello ocasionaba que cualquier
modificación en los datos podía requerir la modificación en todas las funciones del programa, en correspondencia con los
cambios en los datos.
En la Programación Orientada a Objetos la situación es diferente. La utilización de objetos permite un mayor nivel de
abstracción que con la Programación Estructurada, y ofrece las siguientes diferencias con respecto a ésta:
El programador organiza su programa en objetos, que son representaciones del mundo real que están más cercanas a la
forma de pensar de la gente.
Los datos, junto con las funciones que los manipulan, son parte interna de los objetos y no están accesibles al resto de los
objetos. Por tanto, los cambios en los datos de un objeto sólo afectan a las funciones definidas para ese objeto, pero no al resto
de la aplicación.
Todos los programas escritos bajo el paradigma orientado a Objetos se pueden escribir igualmente mediante la Programación
Estructurada. Sin embargo, la Programación Orientada a Objetos es la que mayor facilidad presenta para el desarrollo de programas
basados en interfaces gráficas de usuario.
Autoevaluación
Marca las afirmaciones que sean correctas, referidas a la Programación Orientada a Objetos.
Los datos, junto con las funciones que los manipulan, son parte interna de los objetos y no están accesibles al
resto de los objetos.
Los programas se crean y estructuran de acuerdo con la arquitectura de la computadora donde se van a ejecutar.
Los cambios en los datos de un objeto afectan a las funciones definidas para ese objeto así como al resto de la
aplicación.
Al programar organizamos el código en torno a objetos, que son representaciones del mundo real que están más
cercanas a la forma de pensar de la gente.
Mostrar retroalimentación
[Link] 5/65
25/12/2018 [Link]
Solución
1. Correcto
2. Incorrecto
3. Incorrecto
4. Correcto
[Link] 6/65
25/12/2018 [Link]
2.2.- Beneficios.
Según lo que hemos visto hasta ahora, un objeto es cualquier entidad que podemos ver o
apreciar.
Comprensión. Los conceptos del espacio del problema se hayan reflejados en el código del programa, por lo que la mera
lectura del código nos describe la solución del problema en el mundo real.
Modularidad. Facilita la modularidad del código, al estar las definiciones de objetos en módulos o archivos independientes,
hace que las aplicaciones estén mejor organizadas y sean más fáciles de entender.
Fácil mantenimiento. Cualquier modificación en las acciones queda automáticamente reflejada en los datos, ya que ambos
están estrechamente relacionados. Esto hace que el mantenimiento de las aplicaciones, así como su corrección y modificación
sea mucho más fácil. Por ejemplo, podemos querer utilizar un algoritmo más rápido, sin tener que cambiar el programa
principal. Por otra parte, al estar las aplicaciones mejor organizadas, es más fácil localizar cualquier elemento que se quiera
modificar y/o corregir. Esto es importante ya que se estima que los mayores costes de software no están en el proceso de
desarrollo en sí, sino en el mantenimiento posterior de ese software a lo largo de su vida útil.
Seguridad. La probabilidad de cometer errores se ve reducida, ya que no podemos modificar los datos de un objeto
directamente, sino que debemos hacerlo mediante las acciones definidas para ese objeto. Imaginemos un objeto lavadora. Se
compone de un motor, tambor, cables, tubos, etc. Para usar una lavadora no se nos ocurre abrirla y empezar a manipular esos
elementos, ya que lo más probable es que se estropee. En lugar de eso utilizamos los programas de lavado establecidos. Pues
algo parecido con los objetos, no podemos manipularlos internamente, sólo utilizar las acciones que para ellos hay definidas.
Reusabilidad. Los objetos se definen como entidades reutilizables, es decir, que los programas que trabajan con las mismas
estructuras de información, pueden reutilizar las definiciones de objetos empleadas en otros programas, e incluso las acciones
definidas sobre ellos. Por ejemplo, podemos crear la definición de un objeto de tipo Persona para una aplicación de negocios y
deseamos construir a continuación otra aplicación, digamos de educación, en donde utilizamos también personas, no es
necesario crear de nuevo el objeto, sino que por medio de la reusabilidad podemos utilizar el tipo de objeto Persona
previamente definido.
John Johnson.
Autoevaluación
Marca la opción que NO se corresponda con uno de los beneficios de la Programación Orientada a Objetos.
Modularidad.
Reusabilidad.
Complejidad en el mantenimiento.
Comprensión.
No has acertado, la modularidad del código sí es un beneficio de la POO, al estar las definiciones de objetos en
módulos o archivos independientes, hace que las aplicaciones estén mejor organizadas y sean más fáciles de
entender.
Incorrecto. La POO sí facilita la reusabilidad. Los programas que trabajan con las mismas estructuras de
información, pueden reutilizar las definiciones de objetos empleadas en otros programas, e incluso las acciones
definidas sobre ellos.
¡Correcto! Efectivamente, la complejidad en el mantenimiento difícilmente podría ser un beneficio, pero es que
además, la POO facilita el mantenimiento al estar las aplicaciones mejor organizadas, es más fácil localizar
[Link] 7/65
25/12/2018 [Link]
cualquier elemento que se quiera modificar y/o corregir.
No es correcto. Con la POO, los conceptos del espacio del problema se hayan reflejados en el código del
programa, por lo que la mera lectura del código nos describe la solución del problema en el mundo real.
Solución
1. Incorrecto
2. Incorrecto
3. Opción correcta
4. Incorrecto
[Link] 8/65
25/12/2018 [Link]
2.3.- Características.
Cuando hablamos de Programación Orientada a Objetos, existen una serie de características que
se deben cumplir. Cualquier lenguaje de programación orientado a objetos las debe contemplar. Las
características más importantes del paradigma de la programación orientada a objetos son:
de gran utilidad para un buen diseño del software, ya que nos ayuda a comprender mejor el problema y a tener una visión
global de todo el conjunto. Por ejemplo, si pensamos en una clase Vehículo que agrupa las características comunes de todos
ellos, a partir de dicha clase podríamos crear objetos como Coche y Camión. Entonces se dice que Vehículo es una
abstracción de Coche y de Camión.
Modularidad. Una vez que hemos representado el escenario del problema en nuestra aplicación, tenemos como resultado un
conjunto de objetos software a utilizar. Este conjunto de objetos se crean a partir de una o varias clases. Cada clase se
encuentra en un archivo diferente, por lo que la modularidad nos permite modificar las características de la clase que define un
objeto, sin que esto afecte al resto de clases de la aplicación.
Encapsulación. También llamada "ocultamiento de la información". La encapsulación o encapsulamiento es el
mecanismo básico para ocultar la información de las partes internas de un objeto a los demás objetos de la aplicación. Con la
encapsulación un objeto puede ocultar la información que contiene al mundo exterior, o bien restringir el acceso a la misma
para evitar ser manipulado de forma inadecuada. Por ejemplo, pensemos en un programa con dos objetos, un objeto Persona
y otro Coche. <code>Persona se comunica con el objeto Coche para llegar a su destino, utilizando para ello las acciones que
Coche tenga definidas, como por ejemplo, conducir. Es decir, Persona utiliza Coche, pero no sabe cómo funciona
internamente, sólo sabe utilizar sus métodos o acciones.
Jerarquía. Mediante esta propiedad podemos definir relaciones de jerarquías entre clases y
objetos. Las dos jerarquías más importantes son la jerarquía "es un" llamada
generalización o especialización y la jerarquía "es parte de", llamada agregación.
Conviene detallar algunos aspectos:
La generalización o especialización, también conocida como herencia, permite crear
una clase nueva en términos de una clase ya existente (herencia simple) o de varias
clases ya existentes (herencia múltiple). Por ejemplo, podemos crear la clase
CocheDeCarreras a partir de la clase Coche, y así sólo tendremos que definir las nuevas características que tenga.
La agregación, también conocida como inclusión, permite agrupar objetos relacionados entre sí dentro de una clase. Así,
un Coche está formado por Motor, Ruedas, Frenos y Ventanas. Se dice que Coche es una agregación y Motor,
Ruedas, Frenos y Ventanas son agregados de Coche.
Polimorfismo. Esta propiedad indica la capacidad de que varias clases creadas a partir de una antecesora realicen una misma
acción de forma diferente. Por ejemplo, pensemos en la clase Animal y la acción de expresarse. Nos encontramos que cada
tipo de Animal puede hacerlo de manera distinta, los Perros ladran, los Gatos maúllan, las Personas hablamos, etc. Dicho de
otra manera, el polimorfismo indica la posibilidad de tomar un objeto (de tipo Animal, por ejemplo), e indicarle que realice la
acción de expresarse, esta acción será diferente según el tipo de mamífero del que se trate.
Autoevaluación
Completa la frase, rellenando los huecos con la palabra adecuada.
La propiedad que indica la capacidad de que varias clases creadas a partir de una antecesora realicen una misma
acción de forma diferente recibe el nombre de . Eso quiere decir que cuando pedimos a un
que realice una misma acción, la respuesta va a ser dependiendo del objeto que realice
esa acción.
Enviar
Más adelante veremos que las acciones que se envían a los objetos se llaman métodos o mensajes, y que un
mismo método puede reescribirse de formas distintas para distintos tipos de objetos, de forma que el mismo
mensaje enviado a varios objetos de distintos tipos, hará que cada uno lo realice usando su propio código, por
lo que la respuesta puede ser diferente.
[Link] 9/65
25/12/2018 [Link]
Simula (1962). El primer lenguaje con objetos fue B1000 en 1961, seguido por Sketchpad en
1962, el cual contenía clones o copias de objetos. Sin embargo, fue Simula el primer lenguaje
que introdujo el concepto de clase, como elemento que incorpora datos y las operaciones sobre
esos datos. En 1967 surgió Simula 67 que incorporaba un mayor número de tipos de datos,
además del apoyo a objetos.
SmallTalk (1972). Basado en Simula 67, la primera versión fue Smalltalk 72, a la que siguió Quasar
Smalltalk 76, versión totalmente orientada a objetos. Se caracteriza por soportar las principales
propiedades de la Programación Orientada a Objetos y por poseer un entorno que facilita el rápido desarrollo de aplicaciones.
El Modelo-Vista-Controlador ( MVC) fue una importante contribución de este lenguaje al mundo de la programación. El
lenguaje Smalltalk ha influido sobre otros muchos lenguajes como C++ y Java.
C++ (1985). C++ fue diseñado por Bjarne Stoustrup en los laboratorios donde trabajaba, entre 1982 y 1985. Lenguaje que
deriva del C, al que añade una serie de mecanismos que le convierten en un lenguaje orientado a objetos. No tiene recolector
de basura automática, lo que obliga a utilizar un destructor de objetos no utilizados. En este lenguaje es donde aparece el
concepto de clase tal y como lo conocemos actualmente, como un conjunto de datos y funciones que los manipulan.
Eiffel (1986). Creado en 1985 por Bertrand Meyer, recibe su nombre en honor a la famosa torre de París. Tiene una sintaxis
similar a C. Soporta todas las propiedades fundamentales de los objetos, utilizado sobre todo en ambientes universitarios y de
investigación. Entre sus características destaca la posibilidad de traducción de código Eiffel a Lenguaje C. Aunque es un
lenguaje bastante potente, no logró la aceptación de C++ y Java.
Java (1995). Diseñado por James Gosling de Sun Microsystems a finales de 1995. Es un lenguaje orientado a objetos diseñado
desde cero, que recibe muchas influencias de C++. Como sabemos, se caracteriza porque produce un bytecode que
posteriormente es interpretado por la máquina virtual. La revolución de Internet ha influido mucho en el auge de Java.
C# (2000). El lenguaje C#, también es conocido como C Sharp. Fue creado por Microsoft, como una ampliación de C con
orientación a objetos. Está basado en C++ y en Java. Una de sus principales ventajas que evita muchos de los problemas de
diseño de C++.
Autoevaluación
Relaciona los lenguajes de programación indicados con la característica correspondiente, escribiendo el
número asociado a la característica en el hueco correspondiente.
Ejercicio de relacionar
Lenguaje de
Relación Tiene la característica de que …
programación
Simula 3.- Produce un bytecode para ser interpretado por la máquina virtual.
Enviar
C++ fue diseñado basándose en C y añadiéndole la orientación a objetos. Posteriormente, surgiría Java, que
recibió influencias de C++ y de Ada-95.
[Link] 10/65
25/12/2018 [Link]
Caso práctico
María ha hecho un descanso de cinco minutos.
rport
Al principio de la unidad veíamos que el mundo real está compuesto de objetos, y podemos considerar objetos casi cualquier cosa
que podemos ver y sentir. Cuando escribimos un programa en un lenguaje orientado a objetos, debemos identificar cada una de las
partes del problema con objetos presentes en el mundo real, para luego trasladarlos al modelo computacional que estamos creando.
En este contexto, un objeto de software es una representación de un objeto del mundo real, compuesto de una serie de
características y un comportamiento específico. Pero ¿qué es más concretamente un objeto en Programación Orientada a Objetos?
Veámoslo.
Un objeto es un conjunto de datos con las operaciones definidas para ellos. Los objetos tienen un estado y un
comportamiento.
Por tanto, estudiando los objetos que están presentes en un problema podemos dar con la
solución a dicho problema. Los objetos tienen unas características fundamentales que los
distinguen:
[Link] 11/65
25/12/2018 [Link]
Campos, Atributos o Propiedades. Son la parte del objeto que almacena los datos.
También se les denomina variables miembro. Estos datos pueden ser de cualquier tipo
primitivo (boolean, char, int, double, etc.) o ser a su vez otro objeto. Por ejemplo, un objeto
de la clase Coche puede tener varios objetos de la clase Rueda.
Métodos o Funciones Miembro. Son la parte del objeto que lleva a cabo las operaciones
sobre los atributos definidos para ese objeto.
La idea principal es que el objeto reúne en una sola entidad los datos y las operaciones, y para acceder a los datos privados del
objeto debemos utilizar los métodos que hay definidos para ese objeto.
La única forma de manipular la información del objeto es a través de sus métodos. Es decir, si queremos saber el valor de
algún atributo, tenemos que utilizar el método que nos muestre el valor de ese atributo. De esta forma, evitamos que métodos
externos puedan alterar los datos del objeto de manera inadecuada. Se dice que los datos y los métodos están encapsulados
dentro del objeto.
Autoevaluación
Completa el texto escribiendo la palabra adecuada en cada hueco.
El estado de un objeto viene definido por sus , mientras que su comportamiento viene definido por
sus .
Enviar
Son los métodos los que definen las acciones que un objeto puede realizar, y por tanto su comportamiento,
mientras que los atributos, con los valores que toman en un momento concreto, conforman el estado del objeto
en ese momento.
[Link] 12/65
25/12/2018 [Link]
Dentro de un programa los objetos se comunican llamando unos a los métodos de otros. Los métodos están dentro de los objetos
y describen el comportamiento de un objeto cuando recibe una llamada a uno de sus métodos. En otras palabras, cuando un objeto,
objeto1, quiere actuar sobre otro, objeto2, tiene que ejecutar uno de sus métodos. Entonces se dice que el objeto2 recibe un
mensaje del objeto1.
Los distintos mensajes que puede recibir un objeto o a los que puede responder reciben el nombre de
protocolo de ese objeto.
Los objetos se pueden comunicar entre ellos invocando a los métodos de los otros objetos.
Autoevaluación
Cuando un objeto, objeto1, ejecuta un método de otro, objeto2, se dice que el objeto2 le ha mandado un
mensaje al objeto1.
Verdadero Falso
Falso
En este caso se dice que es el objeto1 el que le ha mandado un mensaje al objeto2.
[Link] 13/65
25/12/2018 [Link]
3.3.- Clases.
Hasta ahora hemos visto lo que son los objetos.
Un programa informático se compone de muchos objetos, algunos de los cuales comparten la misma estructura y comportamiento. Si
tuviéramos que definir la estructura y comportamiento del objeto cada vez que queremos crear un objeto, estaríamos utilizando
mucho código redundante. Por ello lo que se hace es crear una clase, que es una descripción de un conjunto de objetos que
comparten una estructura y un comportamiento común. Y a partir de la clase, se crean tantas "copias" o "instancias" como
necesitemos. Esas copias son los objetos de la clase.
Las clases constan de datos y métodos que resumen las características comunes de un conjunto de objetos.
Un programa informático está compuesto por un conjunto de clases, a partir de las cuales se crean objetos que
interactúan entre sí.
Si recuerdas, cuando utilizábamos los tipos de datos enumerados, los definíamos con la palabra reservada enum y la lista de valores
entre llaves, y decíamos que un tipo de datos enum no es otra cosa que una especie de clase en Java. Efectivamente, todas las
clases llevan su contenido entre llaves. Y una clase tiene la misma estructura que un tipo de dato enumerado, añadiéndole una serie
de métodos y variables.
Para declarar una clase en Java se utiliza la palabra reservada class. La declaración de una clase está compuesta por:
Cabecera de la clase. La cabecera es un poco más compleja que como aquí definimos, pero por ahora sólo nos interesa saber
que está compuesta por una serie de modificadores. En este caso hemos puesto public, que indica que es una clase pública a
la que pueden acceder otras clases del programa, la palabra reservada class y el nombre de la clase.
Cuerpo de la clase. En él se especifican encerrados entre llaves los atributos y los métodos que va a tener la clase.
En las unidades anteriores ya hemos utilizado clases, aunque aún no sabíamos apenas nada sobre su significado exacto.
Por ejemplo, en los ejemplos de la unidad o en la tarea, estábamos utilizando clases, todas ellas eran clases principales, no tenían
ningún atributo y el único método del que disponían era el método main().
El método main() se utiliza para indicar que se trata de una clase principal, a partir de la cual va a empezar la
ejecución del programa.
Este método no aparece si la clase que estamos creando no va a ser la clase principal del programa.
[Link] 14/65
25/12/2018 [Link]
Caso práctico
María sigue fuera de la oficina. Esta noche en casa quiere repasar conceptos sobre
Programación Orientada a Objetos, así que aprovecha un momento para llamar a Juan
y le comenta:
Juan sonríe ante la pregunta de María, y le explica que los objetos se crean como si fuera declarando una variable
más, tan sólo que el tipo de datos de dicho objeto será una clase. Tras declararlos hay que instanciarlos con el
operador new para reservar memoria para ellos, y después ya podremos utilizarlos, refiriéndonos a su contenido con el
operador punto.
—Te mando un documento por correo electrónico que lo explica todo muy bien.
Una vez que hemos creado una clase, podemos crear objetos en nuestro programa a partir de esas clases.
Cuando creamos un objeto a partir de una clase se dice que hemos creado una "instancia de la clase". A efectos prácticos, "objeto"
e "instancia de clase" son términos similares. Es decir, nos referimos a objetos como instancias cuando queremos hacer hincapié que
son de una clase particular.
Los objetos se crean a partir de las clases, y representan "casos individuales" de éstas.
Para entender mejor el concepto entre un objeto y su clase, piensa de nuevo en un molde de galletas
y en las propias galletas.
El molde sería la clase, que define las características del objeto, por ejemplo su forma y tamaño. Las
galletas creadas a partir de ese molde son los objetos o instancias, y todos los objetos de esa clase,
aun siendo distintos, se parecerán bastante, ya que tendrán las mismas características generales.
Otro ejemplo, imagina una clase Persona que reúna las características comunes de las personas
(nombre, NIF, color de pelo, color de ojos, peso, altura, etc.) y las acciones que pueden realizar
medea_material
(crecer, dormir, comer, etc.). Posteriormente dentro del programa podremos crear un objeto trabajador
que esté basado en esa clase Persona. Entonces se dice que el objeto trabajador es una instancia de la clase Persona, o que la
clase Persona es una abstracción del objeto trabajador.
Cualquier objeto instanciado de una clase contiene una copia de todos los atributos definidos en la clase. En otras palabras, lo que
está haciendo el operador new al instanciarlo es reservar el espacio necesario en la memoria del ordenador para guardar sus
atributos y métodos, siguiendo para ello las indicaciones que le da la propia clase. Por tanto, cada objeto tiene una zona de
almacenamiento propia donde se guarda toda su información, que será distinta a la de cualquier otro objeto. A las variables
miembro instanciadas también se les llama variables instancia, o simplemente instancias. De igual forma, a los métodos que
manipulan esas variables se les llama métodos de instancia.
En el ejemplo del objeto trabajador, las variables instancia serían colorDePelo, peso, altura, etc. Y los métodos de instancia serían
crecer(), dormir(), comer(), etc.
Autoevaluación
Verdadero Falso
Falso
Una clase es una estructura parecida a un molde para crear objetos a partir de ella.
[Link] 15/65
25/12/2018 [Link]
[Link] 16/65
25/12/2018 [Link]
A la vista de lo anterior, podemos concluir que los objetos tienen un ciclo de vida, en el cual podemos distinguir las siguientes fases:
[Link] 17/65
25/12/2018 [Link]
4.2.- Declaración.
Para la creación de un objeto hay que seguir los siguientes pasos:
Veamos primero cómo declarar un objeto. Para la definición del tipo de objeto debemos emplear la Ramesh NG
siguiente instrucción:
<tipo> nombreObjeto;
Donde:
Los tipos referenciados o referencias se utilizan para guardar la dirección de los datos en la memoria del
ordenador.
Nada más crear una referencia, ésta se encuentra vacía. Cuando una referencia a un objeto no contiene ninguna instancia se dice
que es una referencia nula, es decir, que contiene el valor null. (También se dice que apunta a null). Esto quiere decir que la
referencia está creada, pero que el objeto no está instanciado todavía, es decir, hemos preparado la referencia indicando a qué tipo
de objetos va a apuntar, pero todavía no hemos reservado memoria para el objeto, así que no está apuntando a ninguna posición de
memoria que contenga ese objeto, y para que no haya confusión posible, la referencia apunta a un objeto inexistente llamado null
(nulo).
Cuando veíamos los tipos de datos primitivos, decíamos que Java proporciona un tipo de dato especial para los textos o cadenas de
caracteres que era el tipo de dato String. Veíamos que realmente este tipo de dato es un tipo referenciado y creábamos una
variable mensaje de ese tipo de dato de la siguiente forma:
String mensaje;
Los nombres de la clase empiezan con mayúscula, como String, y los nombres de los objetos con minúscula,
como mensaje, así sabemos qué tipo de elemento se está utilizando.
Pues bien, String es realmente una clase que nos proporciona Java para facilitar el trabajo con cadenas de texto, a partir de la cual
creamos nuestro objeto llamado mensaje.
Si observas, poco se diferencia esta declaración de las declaraciones de variables que hacíamos para los tipos primitivos. Antes
decíamos que mensaje era una variable del tipo de dato String. Ahora realmente vemos que mensaje es una referencia a un objeto
de la clase String. Pero mensaje aún no contiene el objeto porque no ha sido instanciado, veamos cómo hacerlo.
Por tanto, cuando creamos un objeto estamos haciendo uso de una variable que almacena la dirección de ese objeto en memoria.
Esa variable es una referencia o un tipo de dato referenciado, porque no contiene el dato, si no la posición del dato en la memoria
del ordenador.
En las instrucciones anteriores, las variables s y saludo acaban apuntando al mismo objeto de la clase String. Esto implica que
cualquier modificación en el objeto saludo modifica también el objeto al que hace referencia la variable s, ya que realmente son el
mismo. Es decir, cualquier modificación que haga usando saludo, se hará sobre el objeto, y puesto que s apunta al mismo objeto,
será visible también a través de s.
Autoevaluación
Indica si las siguientes afirmaciones son verdaderas o falsas.
[Link] 18/65
25/12/2018 [Link]
Verdadero Falso
Falso
Es falso, puesto que las referencias lo que almacenan es la dirección de memoria en la que realmente están los
datos del objeto. Por eso decimos que "apuntan" al objeto.
A la hora de nombrar clases siguiendo el convenio generalmente aceptado, siempre comenzaremos con
mayúsculas, cada primera letra de cada palabra que forme el nombre de la clase, incluida la primera palabra,
con el resto de letras en minúscula, sin usar espacios en blanco, ni caracteres acentuados, ni signos de $, ni
carácter de subrayado.
Verdadero Falso
Verdadero
Por eso, camionDeCarreras, Camion_De_Carreras, CAMIONDECARRERAS, CamiónDeCarreras, serían ejemplos de
identificadores poco deseables, que no cumplen el convenio, mientras que el nombre apropiado para esta clase
sería CamionDeCarreras.
[Link] 19/65
25/12/2018 [Link]
4.3.- Instanciación.
Una vez creada la referencia al objeto, debemos crear la instancia u objeto a la que va a apuntar esa referencia. Para ello utilizamos
el operador new con la siguiente sintaxis:
Donde:
Durante la instanciación del objeto, se reserva memoria suficiente para el objeto. De esta tarea se manuelfloresv
encarga Java y desempeña un papel muy importante el recolector de basura, que se encarga de
eliminar de la memoria los objetos que ya han quedado descolgados (sin ninguna referencia que los apunte) y por tanto ya no van a
poder volver a ser utilizados, para que la memoria que ocupaban pueda volver a estar disponible para ser usada.
Así estaríamos instanciando el objeto mensaje. Para ello utilizaríamos el operador new y el constructor de la clase String a la que
pertenece el objeto según la declaración que hemos hecho en el apartado anterior. A continuación utilizamos el constructor, que se
llama igual que la clase, String.
En el ejemplo anterior el objeto se crearía con la cadena vacía (""), si queremos que tenga un contenido debemos utilizar parámetros
en el constructor, así:
Java permite utilizar la clase String como si de un tipo de dato primitivo se tratara, por eso no hace falta utilizar el
operador new para instanciar un objeto de la clase String, aunque también permite hacerlo como para cualquier
otra clase. Por tanto las sentencias mensaje=new String("El primer programa"); y mensaje="El primer programa";
son totalmente equivalentes.
Llamamos también tu atención sobre el hecho de que no es lo mismo decir que una referencia de tipo String
apunte a la cadena vacía ("" , que es un String que no tiene ningún carácter) que decir que apunte a null (que no
es un String, sino una forma de indicar que no apunta a ningún objeto). La cadena vacía sí es un objeto.
[Link] 20/65
25/12/2018 [Link]
4.4.- Manipulación.
Una vez creado e instanciado el objeto ¿cómo accedemos a su contenido?
Para acceder a los atributos y métodos del objeto utilizaremos el nombre del objeto seguido del operador punto (.) y el nombre del
atributo o método que queremos utilizar. Cuando utilizamos el operador punto se dice que estamos enviando un mensaje al objeto.
La forma general de enviar un mensaje a un objeto es:
[Link]
Por ejemplo, para acceder a las variables instancia o atributos se utiliza la siguiente sintaxis:
[Link]
Y para acceder a los métodos o funciones miembro del objeto se utiliza la sintaxis:
En la sentencia anterior parametro1, parametro2, etc., son los parámetros que utiliza el método. Aparecen entre corchetes para indicar
que son opcionales, ya que puede haber métodos que no lleven parámetros.
Para entender mejor cómo se manipulan objetos vamos a utilizar un ejemplo. Para ello necesitamos la Biblioteca de Clases Java o
API (Application Programming Interface - Interfaz de programación de aplicaciones). Uno de los paquetes de librerías o bibliotecas es
[Link]. Este paquete contiene clases destinadas a la creación de objetos gráficos e imágenes. Vemos por ejemplo cómo crear un
rectángulo.
En primer lugar instanciamos el objeto utilizando el método constructor, que se llama igual que el objeto, e indicando los parámetros
correspondientes a la posición y a las dimensiones del rectángulo:
La sentencia anterior declara la variable rectangulo como una referencia de tipo Rectangle, y hace que apunte a un nuevo objeto que
se crea al invocar al constructor con el operador new. El constructor recibe como parámetros las coordenadas de la esquina superior
izquierda, que sería el punto (50, 50) en la pantalla, y el ancho y alto del mismo (longitud de la base y la altura), que sería 150 en
ambos casos.
Una vez instanciado el objeto rectangulo, si queremos cambiar el valor de los atributos utilizamos el operador punto. Por ejemplo,
para cambiar la dimensión del rectángulo, para que tanto su altura como su base sean 100, en lugar de los 150 que le habíamos
asignado, se haría modificando directamente el valor de sus atributos así::
[Link] = 100 ;
[Link] = 100 ;
O bien, podemos utilizar un método para hacer algo similar a lo anterior. Por ejemplo, la siguiente sentencia, fija el tamaño de
rectangulo a 200 por 200, tanto de base como de altura.
[Link](200,200) ;
[Link] 21/65
25/12/2018 [Link]
Debes conocer
En el siguiente vídeo se explican los conceptos de clase y objeto y se pone un ejemplo de su uso.
[Link] 22/65
25/12/2018 [Link]
En Java la destrucción de objetos corre a cargo del recolector de basura (garbage collector). ¡Un
gran invento!, ya que nos permite como programadores prácticamente desentendernos de ese asunto,
sabiendo además que nunca van a producirse problemas por olvidarse de recoger la basura
adecuadamente, como ocurría en otros lenguajes.
Pat Pilon
El recolector de basura es un sistema de destrucción automática de objetos que ya no son utilizados.
Lo que se hace es liberar una zona de memoria que había sido reservada previamente mediante el operador new, pero que ya ha
dejado de estar referenciada, es decir, ya no hay forma de llegar a ella, y por tanto ya no es posible volver a usar ese objeto. Esto
evita que al programar tengamos que preocuparnos de realizar la liberación de memoria.
El recolector de basura se ejecuta en segundo plano y de manera muy eficiente para no afectar a la velocidad del programa que se
está ejecutando. Lo que hace es que periódicamente va buscando objetos que ya no son referenciados, y cuando encuentra alguno
lo marca para ser eliminado. Después los elimina en el momento que considera oportuno, cuando el procesador está menos
ocupado.
Justo antes de que un objeto sea eliminado por el recolector de basura, se ejecuta su método finalize(). Si queremos forzar que se
ejecute el proceso de finalización de todos los objetos del programa podemos utilizar el método runFinalization() de la clase System.
La clase System forma parte de la Biblioteca de Clases de Java y contiene diversas clases para la entrada y salida de información,
acceso a variables de entorno del programa y otros métodos de diversa utilidad. Para forzar el proceso de finalización ejecutaríamos:
[Link]();
Autoevaluación
Las fases del ciclo de vida de un objeto son: Creación, Manipulación y Destrucción.
Verdadero Falso
Verdadero
Efectivamente, los objetos tienen un tiempo de vida limitado y esas son las fases que atraviesan durante su vida
útil.
[Link] 23/65
25/12/2018 [Link]
Caso práctico
María está contenta con lo que está aprendiendo sobre Java, básicamente se trata de
ampliar sus conocimientos y con la experiencia que ella tiene no le resultará difícil
ponerse a programar en poco tiempo.
Por lo pronto, María continúa con el documento facilitado por Juan, ahora tiene que ver
Seudonimoanonimo cómo se utilizan los métodos, aunque intuye que no va a ser algo muy diferente a las
funciones y procedimientos de cualquier otro lenguaje.
Los métodos, junto con los atributos, forman parte de la estructura interna de un objeto. Los
métodos contienen la declaración de variables locales y las operaciones que se pueden realizar
para el objeto, y que son ejecutadas cuando el método es invocado. Se definen en el cuerpo de
la clase y posteriormente son instanciados para convertirse en métodos de instancia de un
objeto.
Para utilizar los métodos adecuadamente es conveniente conocer la estructura básica de que
disponen.
Al igual que las clases, los métodos están compuestos por una cabecera y un cuerpo. La
cabecera también tiene modificadores, en este caso hemos utilizado public para indicar que el
método es público, lo cual quiere decir que le pueden enviar mensajes no sólo los métodos del
objeto sino los métodos de cualquier otro objeto externo. Veremos más adelante los
modificadores que se pueden usar y lo que significa cada uno.
Dentro de un método nos encontramos el cuerpo del método que contiene el código de la acción
a realizar. Las acciones que un método puede realizar son:
[Link] 24/65
25/12/2018 [Link]
Por valor. El valor de los parámetros no se devuelve al finalizar el método, es decir, cualquier
modificación que se haga en los parámetros no tendrá efecto una vez se salga del método. Esto es así
porque cuando se llama al método desde cualquier parte del programa, dicho método recibe una copia
de los argumentos, por tanto cualquier modificación que haga será sobre la copia, no sobre las variables
originales.
Por referencia. La modificación en los valores de los parámetros sí tienen efecto tras la finalización del Wendy House
método. Cuando pasamos una variable a un método por referencia lo que estamos haciendo es pasar la
dirección del dato en memoria, por tanto cualquier cambio en el dato seguirá modificado una vez que salgamos del método.
En el lenguaje Java, todas las variables se pasan por valor, excepto los objetos que se pasan por referencia. En Java, la
declaración de un método tiene dos restricciones:
En un método hay que indicar qué tipo de valor devuelve (o bien void). Este valor de retorno es el valor que devuelve el
método cuando termina de ejecutarse, al método o programa que lo llamó. Puede ser un tipo primitivo, un tipo referenciado o
bien el tipo void, que indica la ausencia de valor de retorno.
Un método tiene un número fijo de argumentos. Los argumentos son variables a través de las cuales se pasa información al
método desde el lugar del que se llame, para que éste pueda utilizar dichos valores durante su ejecución. Los argumentos
reciben el nombre de parámetros cuando aparecen en la declaración del método.
Según hemos visto en el apartado anterior, la cabecera de un método se declara como sigue:
public tipoDeDatoDevuelto nombreMetodo (listaDeParametros) // Cabecera<br />{ // Cuerpo del método<br />}<br />
Como vemos, el tipo de dato devuelto aparece después del modificador public y se corresponde con el valor de retorno. (Aunque la
declaración puede terminar en punto y coma, como se ve en el ejemplo anterior, lo normal es que además de la declaración de la
cabecera, incluyamos la definición completa del método, lo que significa poner las sentencias del cuerpo del método entre llaves,
justo en el lugar donde aparece el punto y coma en la sentencia anterior).
La lista de parámetros aparece al final de la cabecera del método, justo después del nombre, encerrados entre signos de paréntesis
y separados por comas. Se debe indicar el tipo de dato de cada parámetro así:
Cuando se llame al método, se deberá utilizar el nombre del método, seguido de los argumentos que deben coincidir con la lista de
parámetros.
La lista de argumentos en la llamada a un método (lista de parámetros actuales) debe coincidir en número, tipo y orden
con los parámetros incluidos en la declaración del método (lista de parámetros formales), ya que de lo contrario se
produciría un error de sintaxis.
[Link] 25/65
25/12/2018 [Link]
5.2.- Constructores.
¿Recuerdas cuando hablábamos de la creación e instanciación de un objeto?
Decíamos que utilizábamos el operador new seguido del nombre de la clase y un paréntesis. Además, el nombre de la clase era
realmente el constructor de la misma, de ahí la necesidad de poner paréntesis, y lo definíamos como un método especial que sirve
para inicializar valores. En este apartado vamos a ver un poco más sobre los constructores.
Un constructor es un método especial con el mismo nombre de la clase y que no devuelve ningún valor de forma
explícita tras su ejecución, aunque implícitamente devuelve el objeto que se está creando.
Con la anterior instrucción estamos creando un objeto fecha de tipo Date, que contendrá la fecha
y hora actual del sistema.
La estructura de los constructores es similar a la de cualquier método, salvo que no tiene que indicarse explícitamente el tipo de dato
devuelto porque ya está claro que lo que devuelve es el objeto que crea. Está formada por una cabecera y un cuerpo, que contiene
la inicialización de atributos y resto de instrucciones del constructor.
Cuando definimos constructores personalizados, el constructor por defecto deja de existir, y si no definimos nosotros un constructor
sin argumentos cuando intentemos utilizar el constructor por defecto nos dará un error de compilación.
Autoevaluación
Marca las opciones que sean correctas.
Un constructor es un método que puede ser invocado en cualquier momento para un objeto, para que éste quede
reinicializado, con todos sus atributos a valores nulos: 0 para atributos numéricos, false para boolean, y null para
referencias.
Es siempre obligatorio definir un constructor en una clase, ya que de lo contrario resultaría imposible crear
objetos de esa clase.
Una clase puede definir varios constructores, que obligatoriamente se llamarán todos igual, como la clase,
diferenciándose por su lista de parámetros. En caso de que hayamos declarado algún constructor personalizado
con parámetros en una clase, Java ya no creará implícitamente el constructor por defecto, que creaba el objeto
inicializándolo a valores nulos: 0 para atributos numéricos, false para boolean, y null para referencias.
[Link] 26/65
25/12/2018 [Link]
Mostrar retroalimentación
Solución
1. Incorrecto
2. Correcto
3. Incorrecto
4. Correcto
[Link] 27/65
25/12/2018 [Link]
De hecho, se aconseja no inventarse nombres distintos para los parámetros que se usan para recoger el valor que se va a
asignar a un atributo, es preferible llamarle igual a dos cosas que en el fondo se refieren al mismo atributo, y distinguir
parámetro y atributo por medio del operador this.
Vamos a ilustrar mediante un ejemplo la utilización de objetos y métodos, así como el uso de parámetros y el operador this. Aunque
la creación de clases la veremos en las siguientes unidades, en este ejercicio creamos una pequeña clase para que podamos
instanciar el objeto con el que vamos a trabajar.
Las clases se suelen representar como un rectángulo, y dentro de él se sitúan los atributos y los métodos de dicha clase.
En la imagen, la clase Pajaro está compuesta por tres atributos, uno de ellos el nombre y otros dos que indican la posición del ave,
posX y posY. Tiene dos métodos constructores y un método volar(). Como sabemos, los métodos constructores reciben el mismo
nombre de la clase, y puede haber varios para una misma clase, dentro de ella se diferencian unos de otros por los parámetros que
utilizan.
Ejercicio resuelto
Dada una clase principal llamada Pajaro, se definen los atributos y métodos que aparecen en la imagen. Los métodos
realizan las siguientes acciones:
Pajaro(). Constructor por defecto. En este caso, el constructor por defecto no contiene ninguna instrucción, ya
que Java inicializa de forma automática las variables miembro, si no le damos ningún valor.
Pajaro(String nombre, int posX, int posY). Constructor que recibe como argumentos una cadena de texto y dos
enteros para inicializar el valor de los atributos.
volar(int posX, int posY). Método que recibe como argumentos dos enteros: posX y posY, y devuelve un valor de
tipo double como resultado, usando la palabra clave return. El valor devuelto es el resultado de aplicar un
desplazamiento de acuerdo con la siguiente fórmula:
Diseña un programa que utilice la clase Pajaro, cree una instancia de dicha clase y ejecute sus métodos.
Mostrar retroalimentación
Lo primero que debemos hacer es crear la clase Pajaro, con sus métodos y atributos. De acuerdo con los datos
que tenemos, el código de la clase sería el siguiente:
Debemos tener en cuenta que se trata de una clase principal, lo cual quiere decir que debe contener un método
main() dentro de ella. En el método main() vamos a situar el código de nuestro programa.
Sin embargo, debes tener en cuenta que ésta no es la forma más correcta de hacerlo y que el método main()
debería estar en otra clase. Es mucho mejor separar la definición de la clase Pajaro , que quedaría como una
definición de un tipo de datos, de lo que es el uso de esa clase creando y manipulando objetos, que sería lo que
se haría desde el método main() alojado en otra clase, que sería la clase principal del programa. La idea es
simple si piensas en String: la clase String define un tipo de dato (valores que puede tomar, y operaciones que
pueden hacerse con ellos), pero no dispone de ningún método main(), por lo que será la clase principal de
nuestra aplicación, para la que nosotros creamos el método main(), la que definirá objetos de tipo String y los
manipulará haciendo usos de los métodos definidos en String, pero desde dentro del método main() de nuestra
clase principal.
El ejercicio dice que tenemos que crear una instancia de la clase y ejecutar sus métodos, entre los que están el
constructor y el método volar(). También es conveniente imprimir el resultado de ejecutar el método volar(). Por
[Link] 28/65
25/12/2018 [Link]
tanto, lo que haría el programa sería:
Para inicializar el objeto utilizaremos el constructor con parámetros, después ejecutaremos el método volar() del
objeto creado y finalmente imprimiremos el valor que nos devuelve el método. El código de la clase main()
quedaría como sigue:
Si quieres acceder al archivo completo del ejercicio puedes utilizar el siguiente enlace:
[Link] 29/65
25/12/2018 [Link]
Los métodos estáticos son aquellos métodos definidos para una clase que se pueden usar
directamente, sin necesidad de crear un objeto de dicha clase. También se llaman métodos de
clase.
El nombre del método, si lo llamamos desde la misma clase en la que se encuentra definido.
nombreMetodoEstatico();
El nombre de la clase, seguido por el operador punto (.) más el nombre del método estático, si lo llamamos desde una clase
distinta a la que se encuentra definido. Esta será la forma habitual de usar los métodos estáticos:
[Link]();
El nombre del objeto, seguido por el operador punto (.) más el nombre del método estático. Esta forma se podría usar cuando
tengamos un objeto instanciado de la clase en la que se encuentra definido el método estático, pero siempre será preferible
invocarlo mediante el nombre de la clase, ya que al invocarlo con un objeto, da la sensación de que es "un mensaje para
ese objeto", que hace algo exclusivamente con ese objeto, cuando en realidad hace algo para la clase, para todos los objetos
de la clase:
[Link]();
Es muy recomendable que cualquier método estático se invoque siempre referenciado por el nombre de la clase
en la que está definido, (tanto si se invocan desde la misma clase, como si se invocan desde una clase distinta,
como si existen objetos de la clase con los que se podría invocar si se quisiera), justamente para hacer explícito
que se trata de un método estático sin más que ver la sentencia donde se invoca, quedando claro que hace algo
para la clase, y no para un objeto particular. Es decir, como:
[Link]();
Los métodos estáticos no afectan al estado de los objetos instanciados de la clase (variables de instancia), y suelen utilizarse para
realizar operaciones comunes a todos los objetos de la clase. Por ejemplo, si necesitamos contar el número de objetos
instanciados de una clase, podríamos utilizar un método estático que fuera incrementando el valor de una variable entera de la clase
conforme se van creando los objetos. Además, podría haber un método para consultar ese total de objetos creado, y debería ser
estático, porque yo podría querer consultar el número de elementos que existen mediante ese método, incluso en el caso de que
no existiera ningún objeto de dicha clase que poder usar para invocar al método. Mediante el nombre de la clase sí podría al ser
estático.
En la Biblioteca de Clases de Java existen muchas clases que contienen métodos estáticos. Pensemos en las clases que ya hemos
utilizado en unidades anteriores, como hemos comentado la clase String con todas las operaciones que podíamos hacer con ella y
con los objetos instanciados a partir de ella. O bien la clase Math. para la conversión de tipos de datos. Todos ellos son métodos
estáticos que la API de Java define para esas clases. Lo importante es que tengamos en cuenta que al tratarse de métodos
estáticos, para utilizarlos no necesitamos crear un objeto de dichas clases.
Autoevaluación
Los métodos estáticos, también llamados métodos de instancia, suelen utilizarse para realizar operaciones
comunes a todos los objetos de la clase.
Verdadero Falso
Falso
[Link] 30/65
25/12/2018 [Link]
Los métodos estáticos no son métodos de instancia porque se pueden utilizar directamente, referenciándolos
con el nombre de la clase a la que pertenecen, sin necesidad de crear un objeto de la clase para ello.
[Link] 31/65
25/12/2018 [Link]
Caso práctico
—¡Vaya! -exclama María- No consigo encontrar la clase Persona dentro del conjunto de
clases que hasta ahora he creado.
—¿Ah sí? Pues es justo lo que necesito para resolver este desorden. Voy a ponerme
JJ Merelo con ello -añade María.
Conforme nuestros programas se van haciendo más grandes, el número de clases va creciendo. Meter todas las clases en único
directorio no ayuda a que estén bien organizadas, lo mejor es hacer grupos de clases, de forma que todas las clases que estén
relacionadas o traten sobre un mismo tema estén en el mismo grupo.
Un paquete de clases es una agrupación de clases que consideramos que están relacionadas entre sí o tratan de
un tema común.
Las clases de un mismo paquete tienen un acceso privilegiado a los atributos y métodos de otras clases de dicho
paquete, una especie de "relación de confianza". Es por ello por lo que los paquetes son también, en cierto modo,
unidades de encapsulación y ocultación de información.
Java nos ayuda a organizar las clases en paquetes. En cada fichero .java que hagamos, al principio,
podemos indicar a qué paquete pertenece la clase que hagamos en ese fichero.
Los paquetes se declaran utilizando la palabra clave package seguida del nombre del paquete. Para
establecer el paquete al que pertenece una clase hay que poner una sentencia de declaración como la
siguiente al principio de la clase:
package Nombre_de_Paquete;
Seth Schoen
Por ejemplo, si decidimos agrupar en un paquete "ejemplos" un programa llamado "Bienvenida", pondríamos en nuestro fichero
[Link] lo siguiente:
El código es exactamente igual que como hemos venido haciendo hasta ahora, solamente hemos añadido la línea "package
ejemplos;" al principio. En la imagen se muestra cómo aparecen los paquetes en el entorno integrado de Netbeans.
Debes conocer
En el siguiente fichero puedes ver una demostración de cómo hemos creado el proyecto Bienvenida:
[Link] 32/65
25/12/2018 [Link]
import [Link];
npslibrarian
Se pueden importar todas las clases de un paquete con una sentencia import. Por ejemplo, para importar todas las clases del
paquete [Link], se puede hacer así:
import [Link].*;
Es importante aclarar que usando el asterisco, importamos las clases del paquete, pero NO se importan las clases de los
subpaquetes que pudiera tener.
Las sentencias import (puede haber varias) deben aparecer al principio de la clase, justo después de la sentencia package, si ésta
existiese.
También podemos utilizar una clase sin importarla con la sentencia import, en cuyo caso cada vez que queramos usarla debemos
indicar su ruta completa:
Reflexiona
En unidades anteriores hemos hecho uso de clases como String, o Math, que si consultamos en la documentación de la
API, pertenecen al paquete [Link] y sin embargo, nunca hemos tenido que usar ninguna sentencia import
[Link]; ni import [Link]; ni tampoco import [Link].*; y a pesar de ello todo funcionaba
correctamente.
¿No habíamos quedado en que siempre había que importar las clases de otros paquetes que quisiéramos usar?
Por otra parte, ¿qué es preferible, importar las clases una a una o importar todas las clases del paquete usando el
asterisco?
Mostrar retroalimentación
En principio es así, cuando se quiere usar una clase de otro paquete, hay que indicarlo expresamente con una
sentencia import, pero el paquete [Link] es una excepción. Este paquete contiene una serie de clases tan
importantes, que sin él sería imposible hacer nada en Java, ya que contiene, por ejemplo, la propia clase Object,
de la que heredan todas las demás clases, y también toda una serie de clases de uso tan frecuente, que sería
realmente tedioso y molesto tener que ir importándolas cada vez que se van a usar, lo que supondría
importarlas prácticamente siempre, como es el caso de por ejemplo, String. Por eso Java nos ahorra el trabajo e
importa implícitamente todas las clases de ese paquete, lo que nos permite usarlas sin preocuparnos de hacer
nada más.
Respecto a la segunda cuestión, vamos a responderla con una especie de FAQ sobre el uso de import, que
pueden ayudar a entender mejor su funcionamiento.
¿Importar las clases hace que mi archivo (.class o .jar) sea más largo?No, la sentencia import sólo
proporciona al compilador una ruta donde ir a buscar las clases cuando las necesita.
¿Es menos eficiente importar todas las clases de un paquete usando .* que importar sólo las que
vaya a usar con una sentencia import para cada una?No. La búsqueda de nombres es muy eficiente y no
hay diferencia práctica, dado que "no se importa nada realmente", sólo se indica la ruta donde buscar, y si es
la misma para toda una serie de clases, es suficiente con poner la ruta para todas, en lugar de poner la ruta
una a una.
¿No queda mejor documentado el código si se usan import distintos para importar cada clase de
forma individual?Podría parecer que sí, pero la realidad es que NO, porque tiene una serie de desventajas:
Es "duro" acordarse de borrar las clases de la lista cuando dejen de usarse en futuras versiones de un
programa, por lo que puede darse el caso de que una clase que ha dejado de usarse siga teniendo su
sentencia import, por lo que en este caso, al verlo, si vamos a buscar qué se hace con esa clase que
ha dejado de usarse nos podemos volver locos, así que en vez de una ayuda a la documentación
puede acabar siendo un error de documentación.
Importar explícitamente una única clase permite que "accidentalmente" pueda definir clases propias
cuyos nombres entran en conflicto con los nombres de las clases en las librerías estándar, lo cual es
[Link] 33/65
25/12/2018 [Link]
poco deseable. Usando un import para todo un paquete con .* , ayudamos en realidad a prevenir ese
accidente.
Si ya he importado, por ejemplo, [Link].*, ¿por qué tengo que importar también [Link].*?La
sentencia import con la plantilla * sólo establece una ruta, que sólo permite importar las clases de esa ruta
(ese paquete) y no los subpaquetes, que serían rutas distintas. (Piensa que es como si cada paquete fuera
una carpeta, que puede tener subcarpetas).
¿Por qué no necesito usar un import con las clases String, System, Math, etc.?Esto ya se explicó con
más detalle al comienzo, pero resumidamente, esas clases están en el paquete [Link], que contiene
clases tan importantes y necesarias que el lenguaje las incluye por defecto, sin necesidad de usar
explícitamente import.
¿Es importante el orden en que se escriban las sentencias import?No lo es. Sólo es aconsejable
intentar escribirlas de forma que sean más legibles. Por ejemplo, agrupando los import que tengan cierta
relación, etc.
Resumen textual para el vídeo "Tutorial de Java en español- Capítulo 13 – Clases y Objetos".
La siguiente parte del vídeo habla sobre la utilización de objetos y clases en Java:
Resumen textual para el vídeo "Tutorial de Java en español- Capítulo 14 – Clases y Objetos."
Autoevaluación
Es preferible importar todas las clases que necesitemos mediante su propia sentencia import, ya que si
usamos .* estaremos añadiendo a nuestra aplicación el código de toda una serie de clases del paquete que no
necesitamos, y que sólo servirán para aumentar el tamaño de la aplicación, alargando el tiempo de
compilación, además.
Verdadero Falso
[Link] 34/65
25/12/2018 [Link]
Falso
La sentencia import "no importa código" a nuestra aplicación, ni aumenta el tamaño de la misma. Sólo aporta
una referencia al compilador para que sepa dónde tiene que ir a buscar las clases cuando lo necesite, pero
hasta ese momento, no añade nada.
[Link] 35/65
25/12/2018 [Link]
Tom
/<directorio_usuario>/Proyecto_Bienvenida/ejemplos/[Link]
Debemos tener cuidado con las mayúsculas y las minúsculas, para evitar problemas, tenemos que poner el nombre en "package"
exactamente igual que el nombre del subdirectorio.
Para compilar la clase [Link] que está en el paquete ejemplos debemos situarnos en el directorio padre del paquete y
compilar desde ahí:
$ cd /<directorio_usuario>/Proyecto_Bienvenida
$ javac ejemplos/[Link]
$ cd /<directorio_usuario>/Proyecto_Bienvenida
$ java ejemplos/Bienvenida
Bienvenido a Java
Afortunadamente, si el proyecto lo hemos creado desde un entorno integrado como Netbeans, podemos delegar en que
será el entorno quien se encargue de estos detalles, la compilación y ejecución se realizará al ejecutar la opción Run File
(Ejecutar archivo) o hacer clic sobre el botón Ejecutar de la barra de herramientas.
[Link] 36/65
25/12/2018 [Link]
[Link]
package [Link];
package [Link];
A nivel de sistema operativo, tendríamos que crear los subdirectorios basicos y avanzados dentro del directorio ejemplos, y meter ahí
las clases que correspondan.
Para compilar, en el directorio del proyecto habría que compilar poniendo todo el path hasta llegar a la clase. Es decir, el nombre de
la clase va con todos los paquetes separados por puntos, por ejemplo [Link].
/<directorio_usuario>/Proyecto_Bienvenida/ejemplos/basicos/[Link]
$ cd /<directorio_usuario>/Proyecto_Bienvenida
$ javac ejemplos/basicos/[Link]
$ java ejemplos/basicos/Bienvenida
Hola Mundo
La Biblioteca de Clases de Java se organiza haciendo uso de esta jerarquía de paquetes. Así por ejemplo, si quiero acceder a la
clase Date, tendré que importarla indicando su ruta completa, o sea, [Link], así:
import [Link];
Tan bueno como es heredar una biblioteca, es mejor coleccionar una. Augustine Birrel.
[Link] 37/65
25/12/2018 [Link]
Utilizar las clases y métodos de la Biblioteca de Java nos va ayudar a reducir el tiempo de desarrollo
considerablemente, por lo que es importante que aprendamos a consultarla y conozcamos las clases
más utilizadas.
[Link]. Contiene las clases que gestionan la entrada y salida, ya sea para manipular ficheros, leer o escribir en pantalla, en
memoria, etc. Este paquete contiene por ejemplo la clase BufferedReader que se utiliza para la entrada por teclado.
[Link]. Contiene las clases básicas del lenguaje. Este paquete no es necesario importarlo, ya que es importado
automáticamente por el entorno de ejecución. En este paquete se encuentra la clase Object, que sirve como raíz para la
jerarquía de clases de Java, o la clase System que ya hemos utilizado en algunos ejemplos y que representa al sistema en el
que se está ejecutando la aplicación. También podemos encontrar en este paquete las clases que "envuelven" los tipos
primitivos de datos, como Integer, Long, Float, Double, etc., lo que proporciona una serie de métodos para cada tipo de dato de
utilidad, como por ejemplo métodos para las conversiones de datos.
[Link]. Biblioteca de clases de utilidad general para el programador. Este paquete contiene por ejemplo la clase Scanner
utilizada para la entrada por teclado de diferentes tipos de datos, la clase Date, para el tratamiento de fechas, etc.
[Link]. Contiene herramientas para manipulaciones matemáticas.
[Link]. Incluye las clases relacionadas con la construcción de interfaces de usuario, es decir, las que nos permiten construir
ventanas, cajas de texto, botones, etc. Algunas de las clases que podemos encontrar en este paquete son Button, TextField,
Frame, Label, etc.
[Link]. Contiene otro conjunto de clases para la construcción de interfaces avanzadas de usuario. Los componentes que se
engloban dentro de este paquete se denominan componentes Swing, y suponen una alternativa mucho más potente que AWT
para construir interfaces de usuario.
[Link]. Conjunto de clases para la programación en la red local e Internet.
[Link]. Contiene las clases necesarias para programar en Java el acceso a las bases de datos.
[Link]. Biblioteca de clases para implementar mecanismos de seguridad.
Como se puede comprobar, Java ofrece una completa jerarquía de clases organizadas a través de paquetes.
[Link] 38/65
25/12/2018 [Link]
Caso práctico
Juan va a realizar algunas pruebas con el proyecto de la Clínica Veterinaria. Le comenta a María
que lo que tienen ahora mismo es la estructura básica del proyecto, que básicamente se trata de
la definición de algunas clases y objetos que se van a utilizar. Van a necesitar introducir datos por
pantalla para ver cómo se comportan esos objetos, y mostrar por pantalla el resultado de
manipularlos. Para ello utilizarán las clases System y Scanner.
—Estas clases ya las hemos utilizado anteriormente, están en los paquetes [Link] y [Link],
respectivamente, observa en el siguiente código cómo las utilizo —dice Juan.
Peter Megyeri
Los programas a veces necesitan acceder a los recursos del sistema, como por ejemplo los
dispositivos de entrada/salida estándar, para recoger datos de teclado o mostrar datos por
pantalla.
En Java, la entrada por teclado y la salida de información por pantalla se hace mediante la clase
System del paquete [Link] de la Biblioteca de Clases de Java.
Como cualquier otra clase, está compuesta de métodos y atributos. Los atributos de la clase
System son tres objetos que se utilizan para la entrada y salida estándar. Estos objetos son los siguientes:
No se pueden crear objetos a partir de la clase System, sino que se utiliza directamente llamando a cualquiera de sus métodos con el
operador de manipulación de objetos, es decir, el operador punto (.):
[Link]("Bienvenido a Java");
Autoevaluación
La clase System del paquete [Link], como cualquier clase, está formada por métodos y atributos, y además es
una clase que no se puede instanciar, sino que se utiliza directamente.
Verdadero Falso
Falso
[Link] 39/65
25/12/2018 [Link]
La clase System pertenece al paquete [Link].
[Link] 40/65
25/12/2018 [Link]
En el apartado anterior hemos dicho que [Link] es un atributo de la clase System, que está
dentro del paquete [Link]. Pero además, si consultamos la Biblioteca de Clases de Java, nos
damos cuenta de que es un objeto, y como todos los objetos debe ser instanciado. En efecto,
volviendo a consultar la biblioteca de clases nos damos cuenta que [Link] es una instancia Flor Moncada. Captura de pantalla de
la web de Oracle. © (cita)
de una clase de Java que se llama InputStream.
En Java, InputStream nos permite leer en bytes, desde teclado, un archivo o cualquier otro dispositivo de entrada. Con esta clase
podemos utilizar por ejemplo el método read() que permite leer un byte de la entrada o skip(long n), que salta n bytes de la entrada.
Pero lo que realmente nos interesa es poder leer texto o números, no bytes, para hacernos más cómoda la entrada de datos. Para
ello se utilizan las clases:
InputStreamReader. Convierte los bytes leídos en caracteres. Particularmente, nos va a servir para convertir el objeto [Link]
en otro tipo de objeto que nos permita leer caracteres.
BufferedReader. Lee hasta un fin de línea. Esta es la clase que nos interesa utilizar, pues tiene un método readLine() que nos
va a permitir leer caracteres hasta el final de línea.
Sin embargo, seguimos necesitando hacer la conversión si queremos leer números. Por ejemplo, si escribimos un entero 32, en
cadena obtendremos "32". Si recordamos, para convertir cadenas de texto a enteros se utiliza el método estático parseInt() de la
clase Integer, con lo cual la lectura la haríamos así:
Esa operación de conversión de cadena a número sólo funcionará si la cadena introducida realmente se puede convertir en número,
porque representaba a un literal correcto para el tipo numérico de que se trata, en el caso de la sentencia anterior sería int. En caso
contrario, se produciría una excepción de tipo NumberFormatException, (Excepción de Formato de número) que debe ser capturada
y tratada convenientemente.
[Link] 41/65
25/12/2018 [Link]
A continuación vamos a ver un ejemplo de cómo utilizar la clase System para la entrada de datos por
teclado en Java.
Como ya hemos visto en unidades anteriores, para compilar y ejecutar el ejemplo puedes utilizar las
órdenes javac y java, o bien crear un nuevo proyecto en Netbeans y copiar el código que se proporciona en
el archivo anterior.
Observa que hemos metido el código entre excepciones try-catch. Cuando en nuestro programa falla algo, por ejemplo la conversión
de un String a int, Java nos avisa lanzando excepciones. Si "capturamos" esa excepción en nuestro programa, podemos avisar al
usuario de qué ha pasado. Esto es conveniente porque si no tratamos la excepción seguramente el programa se pare y no siga
ejecutándose. El control de excepciones ya lo vimos en la unidad anterior, así que no creo que tengas ningún problema para
entender eso.
[Link] 42/65
25/12/2018 [Link]
El kit de desarrollo de Java, a partir de su versión 1.5, incorpora la clase [Link], la cual Flor Moncada.
Captura de pantalla de la web copyright de Oracle.
permite leer tipos de datos String, int, long, etc., a través de la consola de la aplicación. Por
ejemplo, para leer un dato de tipo entero por teclado sería:
O bien esta otra instrucción para leer una línea completa, incluido texto, números o lo que sea:
En las instrucciones anteriores hemos creado un objeto de la clase Scanner llamado teclado
utilizando el constructor de la clase, al cual le hemos pasado como parámetro la entrada básica del
sistema [Link] que por defecto está asociada al teclado.
Para conocer cómo funciona un objeto de la clase Scanner te proporcionamos el siguiente ejemplo:
[Link] 43/65
25/12/2018 [Link]
En la orden print() y println(), cuando queramos escribir un mensaje y el valor de una variable
Flor Moncada.
debemos utilizar el operador de concatenación de cadenas (+), por ejemplo: Captura de pantalla de la web copyright de Oracle.
[Link](“Bienvenido, “ + nombre);
Las órdenes print() y println() consideran como cadenas de texto sin formato a todas las variables que escriben; por ejemplo, no
sería posible indicar que escriba un número decimal con dos cifras decimales o redondear las cifras, o escribir los puntos de los
miles. Para ello se utiliza la orden printf().
La orden printf() utiliza unos códigos de conversión para indicar de qué tipo es el contenido a mostrar. Estos códigos se caracterizan
porque llevan delante el símbolo %, algunos de ellos son:
%c : escribe un carácter.
%s : escribe una cadena de texto.
%d : escribe un entero.
%f : escribe un número en punto flotante.
%e : escribe un número en punto flotante en notación científica.
Por ejemplo, si queremos escribir el número float 12345.1684 con el punto de los miles y sólo dos cifras decimales la orden sería:
Es importante aclarar que estos códigos de conversión formatean la salida, mostrándola de una manera o de otra, pero no
cambian el valor que internamente tengan las variables. Si en el caso anterior, en lugar de imprimir un valor concreto,
12345.1684, se hubiera impreso una variable con ese mismo valor, aunque se mostrara su valor como 12.345,17 por
pantalla, la variable seguiría teniendo almacenado el valor 12345.1684
Estas órdenes pueden utilizar las secuencias de escape que vimos en unidades anteriores, como " " para crear un salto de línea, " "
para introducir un salto de tabulación en el texto, etc.
Debes conocer
Para conocer algo más sobre la orden printf(), en el siguiente enlace tienes varios ejemplos de utilización:
[Link] 44/65
25/12/2018 [Link]
La separación o diferencia entre la salida estándar y la de error se puede utilizar para redirigir los
mensajes de error a un lugar diferente que los mensajes normales.
Por defecto, tanto out como err tienen su destino en la misma pantalla, o al menos en el caso de la
consola del sistema donde las dos salidas son representadas con el mismo color y no notamos
diferencia alguna. En cambio, en la consola de varios entornos integrados de desarrollo como
NetBeans o Eclipse la salida de err se ve en un color diferente. Teniendo el siguiente código: Ameya arsekar
Como vemos, en un entorno como NetBeans, utilizar las dos salidas nos puede ayudar a una mejor depuración del código.
Aunque por defecto vemos la salida de error en la consola, es posible redirigirla a un fichero por ejemplo, como podemos ver en el
siguiente para saber más.
Autoevaluación
Relaciona cada clase con su función, escribiendo el número asociado a la función en el hueco
correspondiente.
Ejercicio de relacionar
Enviar
PrintStream se utiliza para la salida de datos por pantalla y las otras clases, para la entrada de datos por
teclado.
[Link] 45/65
25/12/2018 [Link]
8.- Excepciones.
Caso práctico
Para que las aplicaciones desarrolladas por BK Programación mantengan una
valoración positiva a lo largo del tiempo por parte de sus clientes, es necesario que
éstas no se vean comprometidas durante su ejecución. Hay innumerables ocasiones en
las que programas que aparentemente son formidables (por su interfaz, facilidad de
uso, etc.) comienzan a generar errores en tiempo de ejecución que hacen que el
usuario desconfíe de ellos día a día.
A lo largo de nuestro aprendizaje de Java nos hemos topado en alguna ocasión con errores, pero éstos suelen ser los que nos ha
indicado el compilador. Un punto y coma que falta por aquí, un nombre de variable incorrecto por allá, pueden hacer que nuestro
compilador nos avise de estos descuidos. Cuando los vemos, se corrigen y obtenemos nuestra clase compilada correctamente.
Pero, ¿sólo existe este tipo de errores? ¿Podrían existir errores no sintácticos en nuestros programas?
Está claro que sí, un programa perfectamente compilado en el que no existen errores de sintaxis, y
que no se detectan por tanto en tiempo de compilación, puede generar otro tipo de errores que
quizá aparezcan cuando estamos usando nuestro programa, en tiempo de ejecución. A estos
errores se les conoce como excepciones, y seguramente has experimentado ya los efectos de este
tipo de errores en algún pequeño programa que, por ejemplo, reciba un número real o una cadena de
caracteres como entrada, cuando el código está esperando un número entero. Si todavía no has
experimentado esto, es un buen momento para probarlo y ver qué pasa.
Aprenderemos a gestionar de manera adecuada estas excepciones y tendremos la oportunidad de GNU Free Documentation License Erik van Leeuwen
utilizar el potente sistema de manejo de errores que Java incorpora. La potencia de este sistema de manejo de errores radica en que:
1.- El código que se encarga de manejar los errores, es perfectamente identificable en los programas. Este código puede estar
separado del código que maneja la aplicación.
2.- Java tiene una gran cantidad de errores estándar asociados a multitud de fallos comunes, como por ejemplo divisiones
por cero, fallos de entrada de datos, formato numérico erróneo, índice fuera de rango en un array o en una cadena, argumentos
no válidos en un método, y un largo etc. Al tener tantas excepciones localizadas, podemos gestionar de manera específica
cada uno de los errores que se produzcan.
En Java se pueden preparar los fragmentos de código que pueden provocar errores de ejecución para que si se produce una
excepción, el flujo del programa sea alterado, transfiriendo el control hacia ciertas zonas o rutinas que han sido creadas previamente
por el programador y cuya finalidad será el tratamiento efectivo de dichas excepciones. Estas rutinas son lanzadas (throw), y toman
el control de la situación, de forma que permiten capturar (catch) la excepción producida, y darle un tratamiento adecuado, o al
menos terminar lo más ordenadamente posible la ejecución del programa, en caso de que se tratara de un error irrecuperable. Si no
se captura la excepción, el programa se detendrá con toda probabilidad, aunque al menos podrá dar una información precisa y
detallada de qué tipo de error se ha producido, en qué línea de código, qué secuencia de instrucciones se han ejecutado hasta llegar
a esa situación. Todo ello es información útil a la hora de corregir el error.
En Java, las excepciones están representadas por clases. La clase [Link] contiene todos los tipos de excepciones.
Todas las excepciones derivarán de la clase Throwable, existiendo clases más específicas. Por debajo de la clase Throwable
existen las clases Error y Exception.
La clase Error se encargará de los errores que se produzcan en la máquina virtual, no en nuestros programas, y que por tanto,
quedan fuera del alcance de lo que nosotros podemos corregir.
La clase Exception será la que nos interese conocer, pues gestiona los errores provocados en nuestros programas.
Java lanzará una excepción en respuesta a una situación poco usual. Cuando se produce un error se genera un objeto asociado a
esa excepción. Este objeto es de la clase Exception o de alguna de sus herederas. Este objeto se pasa al código que se ha definido
para manejar la excepción. Dicho código puede manipular las propiedades del objeto Exception.
El programador también puede lanzar sus propias excepciones. Para ello se usa la cláusula throw (sin s, no confundir
con throws, con s, y que se verá en el epígrafe dedicado a delegación de excepciones). El usuario puede definir
excepciones como subclases de la clase Exception, o de alguna de alguna de sus subclases, y la cláusula throw fuerza la
generación del error invocando al método constructor de un nuevo objeto del tipo de la excepción que se quiere lanzar...
Todo ello, para ser bien entendido, requiere conocimientos de programación orientada a objetos que todavía no se han
abordado en este curso, por lo que se explicará nuevamente y ya con más detalle en próximas unidades.
Las excepciones en Java serán objetos de clases derivadas de la clase base Exception. Existe toda una jerarquía de clases derivada
de la clase base Exception, que se dividen en dos grupos principales:
Las excepciones en tiempo de ejecución, que ocurren cuando el programador no ha tenido cuidado al escribir su código.
[Link] 46/65
25/12/2018 [Link]
Las excepciones que indican que ha sucedido algo inesperado o fuera de control.
[Link] 47/65
25/12/2018 [Link]
Básicamente, para capturar una excepción lo que haremos será declarar bloques de código donde
es posible que ocurra una excepción.
Esto lo haremos mediante un bloque try (intentar). Si ocurre una excepción dentro de estos bloques,
se lanza una excepción. Estas excepciones lanzadas se pueden capturar por medio de bloques
catch. Será dentro de este tipo de bloques donde se hará el manejo de las excepciones.
Beatrice Murch
Su sintaxis es:
<strong>try</strong>{
código que puede generar excepciones;
}<strong>catch</strong> (Tipo_excepcion_1 objeto_excepcion){
instrucciones para manejar excepción de Tipo_excepcion_1;
}<strong>catch</strong> (Tipo_excepcion_2 objeto_excepcion){
<code>instrucciones para manejar excepción de Tipo_excepcion_2;
}<strong>catch</strong> (...){<br /> ...<br />}<strong>finally</strong>{
instrucciones que se ejecutan siempre
}
En esta estructura, la parte catch puede repetirse tantas veces como excepciones diferentes se deseen capturar. La parte finally es
opcional y, si aparece, solo podrá hacerlo una sola vez.
Cada catch maneja un tipo de excepción. Cuando se produce una excepción, se busca el catch que posea el manejador de
excepción adecuado, será el que utilice el mismo tipo de excepción que se ha producido. Esto puede causar problemas si no se tiene
cuidado, ya que la clase Exception es la superclase de todas las demás. Por lo que si se produjo, por ejemplo, una excepción de tipo
AritmethicException y el primer catch captura el tipo genérico Exception, será ese catch el que se ejecute y no los demás.
Por eso el último catch debe ser el que capture excepciones genéricas y los primeros deben ser los más específicos. Lógicamente si
vamos a tratar a todas las excepciones (sean del tipo que sean) igual, entonces basta con un solo catch que capture objetos
Exception.
En la bibliografía sobre excepciones en Java, frecuentemente se cuestiona la utilidad de la cláusula finally, debido a que al ser
instrucciones que se ejecutan siempre, bien podrían sacarse del bloque de manejo de la excepción. Es cierto que finally no aporta la
posibilidad de hacer nada que no se pueda conseguir hacer de forma igualmente clara sin finally, por lo que en lo que a este curso
respecta, su uso queda a criterio del gusto de quien programa. Eso sí, hay que saber que existe y cómo funciona.
Debes conocer
Si deseas conocer en mayor detalle el manejo de excepciones, te aconsejamos el siguiente enlace en el que podrás
encontrar un vídeo ilustrativo sobre su creación y manejo.
Excepciones en Java.
[Link] 48/65
25/12/2018 [Link]
Ejercicio Resuelto
Realiza un programa que lea por teclado un número entero empleando la clase Scanner. Utiliza la estructura try-catch
para que en caso de que se introduzca un valor no esperado, como una letra y dado que saltará una excepción, se
capturen las posibles excepciones y se informe del error. Si la lectura se hizo sin problemas, se mostrará el número
leído.
Mostrar retroalimentación
En el siguiente fichero tienes la clase que captura las excepciones con el bloque try-catch.
En el ejemplo que acabamos de ver se captura cualquier excepción mediante Exception. En esta modificación
el fichero anterior, fíjate que se puede especificar según el tipo de excepción que se capture:
import [Link];
import [Link];
/**
* Clase para entender la captura de excepciones.
*
* @author JJBH
*/
public class EjemploExcepcion {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Autoevaluación
Si en un programa no capturamos una excepción, será la máquina virtual de Java la que lo hará por nosotros,
pero inmediatamente detendrá la ejecución del programa y mostrará una traza y un mensaje de error.
Verdadero Falso
Verdadero
Así es, si un método no gestiona las excepciones que se producen en él, la excepción será pasada al método
que llamó al método. Y así ocurrirá sucesivamente si no existe gestión de las excepciones en niveles
superiores, hasta llegar a la máquina virtual de Java, que informará lo mejor que pueda de lo que ha ocurrido y
detendrá la ejecución del programa de la manera más ordenada posible.
[Link] 49/65
25/12/2018 [Link]
Como hemos comentado, siempre debemos controlar las excepciones que se puedan producir o de lo contrario nuestro software
quedará expuesto a fallos. Que las excepciones las trate la propia máquina virtual, significa haber dejado que "ocurra la catástrofe", y
que el programa se termine de forma abrupta, lo que nunca es deseable.
Interrupción. En este caso se asume que el programa ha encontrado un error irrecuperable. La operación que dio lugar a la
excepción se anula y se entiende que no hay manera de regresar al código que provocó la excepción para intentar reconducir
la situación.
Reanudación. Se puede manejar el error y regresar de nuevo al código que provocó el error.
Java emplea la primera forma, pero puede simularse la segunda mediante la utilización de un bloque try en el interior de un while,
que se repetirá hasta que el error deje de existir. En la siguiente imagen tienes un ejemplo de cómo llevar a cabo esta simulación.
Debes conocer
En este enlace puedes ver explicado algún ejemplo de excepciones.
Como la gestión de excepciones es un asunto bastante importante, te ponemos un enlace más con algún ejemplo
adicional.
Excepciones en Java
Ejercicio Resuelto
Realiza un programa en Java en el que se solicite al usuario la introducción de un número por teclado
comprendido entre el 0 y el 100. Si el usuario no introduce un número en dicho rango, deberá mostrarse un
mensaje de error y volver a pedir la introducción del número.
Además, utilizando el manejo de excepciones, debes controlar la entrada de dicho número y volver a solicitarlo
en caso de que ésta sea incorrecta.
Por último, muestra el número leído por pantalla, junto al número de veces que el usuario ha introducido el
número hasta darlo por bueno.
Mostrar retroalimentación
Accede al siguiente enlace, en el que podrás visualizar cómo podríamos obtener los resultados solicitados en el
enunciado del ejercicio, utilizando estructuras try-catch-finally.
En este programa se solicita repetidamente un número utilizando una estructura do-while, mientras el número
introducido sea menor que 0 y mayor que 100. Se realiza la división entera de 100 entre el número que se lea
por teclado.
Como al solicitar el número pueden producirse los errores siguientes:
[Link] 50/65
25/12/2018 [Link]
Errores de entrada al introducir una letra, o bien al introducir un número real, etc. Por ello capturaremos la
excepción InputMismatchException generada.
Errores aritméticos al intentar dividir por 0, si el usuario introduce un 0 como entrada. Por ello capturaremos
a través de la excepción <code>ArithmeticException generada.
Entonces se hace necesaria la utilización de bloques catch que gestionen cada una de las excepciones que
puedan producirse. Cuando se produce una excepción, se compara si coincide con la excepción del primer
catch. Si no coincide, se compara con la del segundo catch y así sucesivamente. Si se encuentra un catch que
coincide con la excepción a gestionar, se ejecutará el bloque de sentencias asociado a éste.
Si ningún bloque catch coincide con la excepción lanzada, dicha excepción se lanzará fuera de la estructura try-
catch-finally.
El bloque finally, se ejecutará tanto si try terminó correctamente, como si se capturó una excepción en algún
bloque catch. Por tanto, si existe bloque finally éste se ejecutará siempre.
[Link] 51/65
25/12/2018 [Link]
Quizá pudiéramos pensar que debería ser el propio método el que se encargue de sus excepciones,
aunque es posible hacer que la excepción sea resuelta por el código que hizo la llamada. Cuando un
método utiliza una sentencia que puede generar una excepción, pero dicha excepción no es Stockbyte.
capturada y tratada por él, sino que se encarga su gestión a quién llamó al método, decimos que se Uso educativo no comercial
para plataformas públicas de
ha delegado la excepción o que se ha producido una delegación de excepciones. Formación Profesional a distancia.
CD-DVD Num. V43
Para establecer esta delegación, en la cabecera del método se declara el tipo de excepciones que puede generar y que deberán ser
gestionadas por quien invoque a dicho método. Utilizaremos para ello la sentencia throws (con s, no confundir con throw, sin s, y que
sirve para indicar el punto del código donde se quiere lanzar una excepción). Tras la palabra throws se indica qué excepciones puede
provocar el código del método. Si ocurre una excepción en el método, el código abandona ese método y regresa al código desde el
que se llamó al método. Allí se posará en el catch apropiado para esa excepción, que la capturará y manejará adecuadamente. Si no
lo hiciera, la excepción puede seguir propagándose hasta que en el peor de los casos llegara a la máquina virtual, que la trataría
provocando que el programa aborte.
Su sintaxis es la siguiente:
Donde IOException y NumberFormatException, serían dos posibles excepciones que el método leeAnio() podría generar, pero que no
gestiona. Por tanto, un método puede incluir en su cabecera un listado de excepciones que puede lanzar, separadas por comas.
La cláusula throws avisa al compilador de que ese método puede generar errores, pero además avisa al programador de que si usa
ese método, debería capturar y manejar la excepción que puede lanzar, ya que de lo contrario el programa puede "abortar".
Debes conocer
A continuación tienes un artículo muy interesante donde se explica la gestión de excepciones con ejemplos.
Gestión de excepciones
Además te volvemos a remitir al vídeo demostrativo sobre manejo de excepciones en Java que se incluyó en el
epígrafe titulado "capturar una excepción con try".
Autoevaluación
Rellena los huecos con las palabras adecuadas.
[Link] 52/65
25/12/2018 [Link]
La captura y manejo de es la forma en que Java controla los en tiempo de
.
Para ello, se definen bloques de código, mediante la palabra reservada seguida de llaves que delimitan el bloque
de código en el que se puede producir el error. Cuando la excepción se produce el control del programa se transfiere a
la primera cláusula que encuentra, para comprobar si el error es del tipo de de excepción que ahí se captura,
y si no lo es sigue comparando con las siguienes cláusulas que pueda haber. Si encuentra coincidencia con
alguna, ejecuta el bloque de código que contenga, y transfiere el control a la cláusula , si la hubiera. Esta
cláusula, de aparecer, se ejecutará siempre, tanto si se ha producido, capturado y tratado la excepción, como si no.
El usuario puede crear sus propias excepciones, además de forzar la generación de alguna excepción usando la
sentencia . También puede decidir que un método no capture ni trate una determinada excepción, sino que la
para que sea tratada por el código que hizo la llamada, avisando de ello al compilador y al programador,
con la inclusión de la cláusula seguida de los nombres de las excepciones que , separados por
comas, en la cabecera de la declaración del método.
Enviar
Si has tenido dificultades para encontrar las palabras correctas, te recomendamos que vuelvas a repasarte
todos los epígrafes anteriores, dedicados a excepciones, capturas, manejo y delegac
[Link] 53/65
25/12/2018 [Link]
9.- Recursividad.
Caso práctico
En el documento que Juan envió a María por correo electrónico, además de conceptos
sobre Programación Orientada a Objetos, había otra cosa muy interesante que le llamó
mucho la atención, y es la recursividad.
¿Pero esto qué es? ¿Se lo debería preguntar a Juan ahora, o estará durmiendo y lo
molestaré? No sé si podré aguantar hasta mañana,... -piensa María.
¿Has oído alguna vez la máxima de que en la definición no debe usarse lo que se intenta definir?
Parece lógico que si me piden definir lo que es un ordenador, decir que es una especie de
ordenador que permite…, no aporta mucha información, no es la mejor manera de empezar la
definición.
Aunque esa máxima es muy lógica y sensata a la hora de hablar en nuestra vida diaria, ya puedes ir
olvidándola en el caso de la programación, al igual que en matemáticas, donde existen definiciones
por recurrencia:
En programación, usamos el término recursividad para referirnos a procedimientos o métodos que contienen en su
implementación llamadas a sí mismo, es decir un método es recursivo si para ejecutarse se llama a sí mismo.
metodoRecursivo(){
sentencia;
sentencia;
metodoRecursivo();
sentencia;
sentencia;
Pero, si para ejecutar a un método hay que hacer una llamada al mismo método que a su vez hará una llamada al mismo método, y
así sucesivamente, ¿no habremos entrado en un bucle infinito que hará que nunca terminemos?
No, si las cosas se hacen bien. Aunque evidentemente, es posible hacerlas mal. ¿Qué debemos tener en cuenta a la hora de saber
si un método recursivo está bien definido?
Además de la llamada al propio método, deben existir otras sentencias en la definición del método que establezcan al
menos un caso base, es decir, un caso para el que se conoce la solución, y para el que la llamada al método puede devolver
un valor o terminar la ejecución sin necesidad de volver a invocar de nuevo al propio método.
Cada nueva llamada al propio método debe reducir el problema, es decir, debe acercarnos más al caso base.
La solución debe ser correcta para los casos no base. Es decir, debemos ser capaces de expresar correctamente la
solución de un caso a partir de la soluciones de casos menos complejos, para poder construir la solución de cualquier caso a
partir de las soluciones del caso base.
[Link] 54/65
25/12/2018 [Link]
Anónimo.
[Link] 55/65
25/12/2018 [Link]
Sabemos que dado un número entero positivo, el factorial se puede definir de dos formas:
Definición Iterativa. Como el producto de todos los números enteros comprendidos entre 1 y el
propio número:
n != n*(n-1)*(n-2)*…*3*2*1. Además, por convenio, para extender la definición también al cero, Blanca Egea
se define: 0! = 1
Para calcular el factorial de esta forma, tenemos que repetir un ciclo en el que se vaya acumulando el producto del número por el
anterior, hasta que lleguemos a uno.
Definición Recursiva. Como el producto del propio número por el factorial del número anterior.
Es evidente que (n-1)! = (n-1)* (n-2)*…*3*2*1, lo que nos lleva a poder escribir que n! = n * (n-1)!, siendo además 0! = 1 igual
que antes. Acabamos de hacer una definición por recurrencia del factorial de un número. “El factorial de un número vale 1 si el
número es cero, y el producto del propio número por el factorial del anterior, en otro caso.”
Para calcular el factorial de esta forma, es como si le encargáramos la tarea a una persona, que no sabe calcular el valor final del
factorial de n, pero sabe que es n * (n-1)!, y le pregunta a otra persona el valor de (n-1)! Esta persona, tampoco sabe calcular el
valor final de (n-1)!, pero sabe que es (n-1)*(n-2)!, y le pregunta a su vez a otra persona el valor de (n-2)!, y así sucesivamente
hasta que llegamos a preguntarle a una persona el valor de 0! Y esa persona responde que 0! =1. A partir de ese momento, la
persona que le preguntó tiene toda la información para calcular 1!, lo calcula, y le responde a la persona que le preguntó, que
completa el cálculo de 2!, y así sucesivamente, hasta llegar a la persona que calcula (n-1)!, que completa el cálculo y le
proporciona su valor a quien le preguntó, que multiplica ese valor por n y obtiene el valor de n!.
Al igual que tenemos dos definiciones del factorial, una iterativa y otra recursiva, un problema lo podemos resolver mediante un
método que sea iterativo, ajustándose a la primera definición o mediante un método recursivo, que se ajuste a la segunda. La
solución recursiva, en este caso, es más elegante, en el sentido de que genera un código más breve, y más simple de entender,
es muy intuitiva.
La recursividad es una poderosa herramienta en programación y ofrece una alternativa a las soluciones iterativas complejas de
algunos algoritmos.
Los problemas resultan más fáciles de resolver que con estructuras iterativas.
Proporciona soluciones más simples.
Proporciona soluciones elegantes.
Autoevaluación
¿Qué debemos tener en cuenta a la hora de saber si un método recursivo está bien definido? Señala la afirmación
correcta.
Debemos ser capaces de expresar correctamente la solución de un caso a partir de la soluciones de casos
menos complejos, para poder construir la solución de cualquier caso a partir de las soluciones del caso base.
[Link] 56/65
25/12/2018 [Link]
Debemos ser capaces de expresar correctamente la solución de un caso a partir de la soluciones de casos más
complejos
No, no es eso.
No, no es correcto.
Solución
1. Opción correcta
2. Incorrecto
3. Incorrecto
4. Incorrecto
[Link] 57/65
25/12/2018 [Link]
¿Siempre va a existir una solución iterativa o hay casos en los que obligatoriamente tendremos que
usar recursividad?
No sólo no existen casos en los que sea obligatoria, sino que siempre existe una solución
iterativa, y ésta siempre será más eficiente, es decir, necesitará consumir menos recursos de
memoria y de CPU, y obtendrá la solución en menos tiempo.
Lo que ocurre es que a veces, por la naturaleza recursiva del problema, no es fácil encontrar la rob van de Pavert
solución iterativa, o resulta complicada y difícil de entender.
La recursividad se debe usar cuando sea realmente necesaria, es decir, cuando no exista una solución iterativa simple.
Cuando las dos soluciones son fácilmente expresables, siempre será preferible la solución iterativa.
Por otro lado, la recursividad requiere hacer una asignación dinámica de memoria, que no es posible en todos los lenguajes de
programación. (Sí lo es en Java y en otros muchos).
Cada vez que se hace una nueva llamada al método recursivo, es necesario guardar en la pila (stack) todos los datos de la
llamada anterior que aún no ha terminado (todas las variables de memoria que tenga definidas el método), lo que se conoce como
entorno volátil de esa ejecución.
Esto incluye almacenar en la memoria todos los valores de los registros del microprocesador, para poder restablecerlos
posteriormente y continuar por el mismo punto de la ejecución de esa llamada que lo habíamos dejado.
Como puede haber muchas llamadas sucesivas, éstas se van almacenando en la pila, de forma que se irán retirando de ella en el
orden contrario a como se introdujeron. Así, el último en entrar es el primero en salir. (Estructura LIFO). De este modo, el
procesador de la computadora tiene que dedicarse a:
Esa es la causa responsable de que las soluciones recursivas requieran mucho más tiempo de CPU y mucha más memoria.
Con una solución iterativa sólo tendremos un método ejecutándose, por lo que sólo necesitaremos memoria para una copia de cada
una de las variables que usa ese método. Por otro lado, no hay que hacer ninguna operación de almacenar en la pila los datos de la
ejecución para posteriormente reanudarla, ya que la llamada al método iterativo se ejecuta hasta finalizar, sin tener que
intercambiarse con ninguna otra llamada.
En este sentido, el factorial no es el mejor ejemplo que se puede mostrar de uso adecuado de una solución recursiva, ya que existe
una solución iterativa igualmente clara y simple, que siempre va a ser más eficiente.
Autoevaluación
Señala la afirmación correcta. Respecto a la recursividad frente a la iteración, podemos afirmar que:
Si existe una solución recursiva a un problema, no siempre existe una solución iterativa.
A veces, por la naturaleza recursiva del problema, no es fácil encontrar la solución iterativa, o resulta complicada
y difícil de entender.
La solución recursiva necesitará consumir menos recursos de memoria y de CPU, y obtendrá la solución en
menos tiempo.
Incorrecto
¡Muy bien!
Incorrecta.
[Link] 58/65
25/12/2018 [Link]
Solución
1. Incorrecto
2. Opción correcta
3. Incorrecto
4. Incorrecto
[Link] 59/65
25/12/2018 [Link]
Hemos venido contando las características a tener en cuenta sobre la recursividad, su definición, y
algunas consideraciones generales sobre su uso.
Con los ejemplos de los apartados siguientes, pretendemos dar una idea de la recursividad. Son
ejemplos que ayudan por su sencillez y claridad a comprender el concepto de recursividad, pero que
presentan una solución iterativa simple que es igualmente clara y más eficiente (factorial,
Fibonacci y máximo común divisor)
Lee Coursey
No ahondaremos en problemas más complicados, pero que sepas que hay ejemplos que escapan a
las pretensiones del módulo, en los que, a pesar de que existe la solución iterativa, ésta es difícil de imaginar, y la recursividad aporta
una solución simple y elegante. Estos casos son por ejemplo: el problema de las Torres de Hanoi, Ordenación por QuickSort, etc.
También se usa la recursividad en un un tipo especial de problemas, denominados algoritmos de Vuelta atrás o Backtracking, que
consisten en explorar de forma sistemática todos los caminos posibles para alcanzar la solución, y si algún camino nos lleva a un
punto en el que no es posible alcanzar la solución deseada, se vuelve atrás hasta alcanzar un punto en el que es posible continuar
explorando nuevas alternativas. Es el caso de problemas para encontrar la salida de un laberinto, o para calcular los movimientos de
una ficha en el tablero de ajedrez.
Torres de Hanoi.
[Link] 60/65
25/12/2018 [Link]
9.3.1.- Factorial.
Éste es el primer ejemplo de recursividad que vamos a ver. ¿Por qué lo elegimos como el
primero?
Porque es el más simple de todos, y el que más ayuda a aclarar los conceptos.
Primero te recomendamos que veas el código de la versión iterativa. Como puedes observar, esta
solución es totalmente clara, y al ser más eficiente, será preferible a la solución recursiva.
A continuación aparece el enlace a la versión recursiva. Como ves, es una solución elegante, que
ayuda a comprender el concepto de recursividad, pero que no aporta claridad ni sencillez, por lo que al ser menos eficiente que la
solución iterativa, no sería adecuado usar recursividad en este caso.
Autoevaluación
¿Cuáles es la razón fundamental para usar la recursividad? Señala la afirmación correcta.
Los problemas resultan más fáciles de resolver que con estructuras iterativas.
Incorrecto.
Solución
1. Incorrecto
2. Incorrecto
3. Incorrecto
4. Opción correcta
[Link] 61/65
25/12/2018 [Link]
Al igual que en el caso del factorial, existe una solución iterativa que es bastante sencilla y
clara, por lo que la recursividad lo único que aporta es un mayor parecido con la definición de la
función. Pero en este caso, tenemos el agravante de que cada llamada a la función genera dos
nuevas llamadas recursivas, con lo que la eficiencia decrece considerablemente. Se produce
una explosión exponencial del número de llamadas recursivas, repitiéndose además cálculos
de forma innecesaria. Así, resulta aún más desaconsejable el uso de la recursividad en este
caso.
La función Fibonacci calcula el valor del término n-ésimo de la sucesión de Fibonacci, en la que
el primer término es 0, el segundo 1 y a partir de ahí, cada nuevo término se calcula como la east_mountain
suma de los dos inmediatamente anteriores. Puede también inicializarse los dos primeros términos con otros valores, pero lo que no
cambia es la forma de obtener los sucesivos términos.
fib(n) = n, si n = 0 ó n = 1
fib(n) = fib(n-1) + fib(n-2), si n >1
Esta definición de la función es muy clara e intuitiva, y el algoritmo recursivo que la implementa es muy sencillo de hacer, pero muy
ineficiente. Si intentas calcular el término 40 de la sucesión, verás cómo tarda un tiempo considerable en resolverlo, y si introduces
un valor más alto, posiblemente tendrás la sensación de que el ordenador se ha bloqueado, debido a lo que tarda. Ese tiempo, no
obstante, será mayor o menor dependiendo de la potencia de tu ordenador.
Fibonacci
Not Found
The requested URL
/cursos/blocks/recopila/PROG04_CONT_R65_Fibonacci.[Link]
was not found on this server.
Resumen de la presentación.
A continuación presentamos el código de la solución iterativa, que también es claro y fácil de programar, aunque quizás no tan
elegante, pero desde luego es mucho más eficiente. Al ejecutarlo comprueba el tiempo que tarda en ejecutarse para el caso de que
el número sea 100. Prácticamente es instantáneo. Sin embargo, la solución recursiva, ya tardaba mucho más de lo razonable para
números mayores de 40. Claramente, la solución iterativa es mucho más eficiente.
[Link] 62/65
25/12/2018 [Link]
Éste es otro caso en el que la solución iterativa sería más eficiente, y por tanto preferible: el
cálculo del máximo común divisor de dos números por el algoritmo de Euclides. No aporta
por tanto ninguna novedad, salvo la de comprobar que casi cualquier algoritmo iterativo puede
tener una versión recursiva, y mostrar un ejemplo más de problema recursivo.
El cálculo del máximo común divisor de dos números enteros por el algoritmo de Euclides,
consiste en:
Por tanto, el máximo común divisor será el último resto no nulo de esas divisiones sucesivas, que también es el divisor de la última
división para la que se ha obtenido resto 0.
[Link] 63/65
25/12/2018 [Link]
Materiales desarrollados inicialmente por el Ministerio de Educación, Cultura y Deporte y actualizados por el
profesorado de la Junta de Andalucía bajo licencia Creative Commons BY-NC-SA.
Historial de actualizaciones
Versión: 01.03.00 Fecha de actualización: 11/10/18 Autoría: José Javier Bermúdez Hernández
Versión: 01.02.00 Fecha de actualización: 14/11/14 Autoría: José Javier Bermúdez Hernández
Se ha añadido el apartado final de Recursividad, que aunque no viene en normativa, se estima importante para la formación del
alumnado. Además, se han incorporado las sugerencias del curso pasado y algunas imágenes del anexo se han eliminado del
mismo, para incorporar las credenciales en el pie de cada foto.
Versión: 01.01.00 Fecha de actualización: 19/11/13 Autoría: José Javier Bermúdez Hernández
Se ha completado la accesibilidad donde hacía falta, se han renombrado y vuelto a enlazar los recursos para que el nombre
indique correctamente la unidad (aunque no se han enlazado con créditos a pie de foto). Se han modificado los enlaces al
glosario por definiciones dentro del propio eXe. Se han modificado los ejemplos de código para que hagan uso de la
nomenclatura correcta para identificadores de clases, métodos y variables, revisando que en las capturas de pantalla también se
corrigieran l
[Link] 64/65
25/12/2018 [Link]
[Link] 65/65