INTRODUCCIÓN A LA PROGRAMACIÓN ORIENTADA A OBJETOS
1
2
Contenido 1.
PROBLEMAS Y SOLUCIONES ........................................................................................................ 5 1.1.
Objetivos pedagógicos ........................................................................................................ 5
1.2.
Introducción ........................................................................................................................ 5
1.3.
Entidades o clases ............................................................................................................... 7
1.4.
Atributos.............................................................................................................................. 7
1.5.
Comportamiento ............................................................................................................... 10
1.5.1.
Caso de estudio 1 Unidad I: El estudiante ................................................................. 13
1.5.2.
Comprensión del problema ....................................................................................... 14
1.5.3.
Caso de estudio 2 Unidad I: El empleado .................................................................. 18
1.5.4.
Comprensión del problema ....................................................................................... 18
1.6.
Hoja de trabajo 1 Unidad I: La granja ................................................................................ 21
1.6.1. 1.7.
Hoja de trabajo 2 Unidad I: La Constructora ..................................................................... 24
1.7.1. 1.8.
2.
Comprensión del problema ....................................................................................... 22
Comprensión del problema ....................................................................................... 24
Métodos ............................................................................................................................ 27
1.8.1.
Expresiones ............................................................................................................... 28
1.8.2.
Cómo construir un método ....................................................................................... 33
1.8.3.
Declarar variables en Java ......................................................................................... 35
1.8.4.
Envío de mensajes o llamado de métodos ................................................................ 36
1.8.5.
Solución del caso de estudio 2 .................................................................................. 39
1.8.6.
Solución de la hoja de trabajo 1 ................................................................................ 43
1.8.7.
Caso de estudio 3 Unidad I: El estudiante con notas ................................................ 48
1.8.8.
Comprensión del problema ....................................................................................... 48
1.8.9.
Caso de estudio 4 Unidad I: El minimercado............................................................. 56
1.8.10.
Comprensión del problema ....................................................................................... 56
EXPRESIONES Y ESTRUCTURAS DE DECISION ............................................................................ 63 2.1.
Introducción ...................................................................................................................... 63
2.2.
Caso de estudio 1 Unidad II: Juguetería ............................................................................ 68 3
2.2.1.
Comprensión del problema ....................................................................................... 68
2.2.2.
Especificación de la Interfaz de usuario .................................................................... 70
2.2.3.
Otros elementos de modelado ................................................................................. 70
2.2.4.
Instrucciones Condicionales ...................................................................................... 75
2.3.
Hoja de trabajo 1 Unidad II: Autoservicio ......................................................................... 79
2.3.1. 2.4.
Caso de estudio 2 Unidad II: Concesionario ...................................................................... 85
2.4.1.
Comprensión del problema ....................................................................................... 86
2.4.2.
Especificación de la Interfaz de usuario .................................................................... 86
2.4.3.
Otros elementos de modelado ................................................................................. 87
2.5.
Hoja de Trabajo 2 Unidad II: Floristería ............................................................................ 92
2.5.1.
Comprensión del problema ....................................................................................... 93
2.5.2.
Asociaciones opcionales ............................................................................................ 97
2.6. 3.
Comprensión del problema ....................................................................................... 79
Tipos de métodos .............................................................................................................. 98
ESTRUCTURAS CONTENEDORAS ............................................................................................. 103 3.1.
Caso de estudio 1Unidad III: Grupo de estudiantes ........................................................ 103
3.1.1. 3.2.
Hoja de Trabajo 1 Unidad III: VideoTienda ..................................................................... 110
3.2.1. 3.3.
Comprensión del problema ..................................................................................... 111
Caso de estudio 2 Unidad III: Parqueadero ..................................................................... 117
3.3.1. 3.4.
Comprensión del problema ..................................................................................... 104
Comprensión del problema ..................................................................................... 118
Hoja de trabajo 2 Unidad III: Sala de computadores ...................................................... 125
3.4.1.
Comprensión del problema ..................................................................................... 125
BIBLIOGRAFIA .................................................................................................................................. 131
4
1.
PROBLEMAS Y SOLUCIONES
1.1. Objetivos pedagógicos
Al final de esta unidad el estudiante estará en capacidad de: Identificar y seguir las etapas para la solución de un problema Resolver un problema haciendo uso de un programa de computador Manejar los conceptos de creación e invocación de métodos, expresiones, tipos de datos e instanciación. Interactuar con el ambiente de desarrollo Eclipse Crear interfaces gráficas sencillas
1.2. Introducción
Cuando una empresa tiene un problema que puede ser resuelto mediante el uso de un computador, es necesario contactar a un equipo de desarrollo. Éste debe determinar qué desea el cliente para poder dar una solución de calidad, que satisfaga sus necesidades. Especificación del problema El primer paso que debe seguir el equipo de desarrollo para poder dar solución a un problema es entenderlo. Esta etapa se denominada análisis. La salida de esta etapa se denomina especificación del problema. La etapa de análisis considera varios aspectos, a saber: Identificar los requisitos funcionales, es decir, lo que el cliente espera que haga el programa. El programador debe tener una inmensa habilidad para interactuar con el cliente, pues son pocas las ocasiones en las que el cliente sabe con exactitud las funcionalidades que el sistema debe proveer. El programador debe estar en capacidad de reconocer requisitos incompletos, contradictorios o ambiguos. Entender el mundo del problema, es decir, las reglas y estructura de la empresa dentro de la cual va a funcionar el software. Identificar los requisitos no funcionales, todas aquellas restricciones de los servicios o funciones que el sistema debe ofrecer por ejemplo rendimiento, cotas de tiempo, interfaz de usuario, factores humanos, documentación, consideraciones de hardware, características de ejecución, cuestiones de calidad, ambiente físico. El programador debe adicionalmente haber contemplado la viabilidad del sistema, es decir, haber analizado el conjunto de necesidades para lograr proponer una solución en el plazo deseado que contemple restricciones económicas, técnicas, legales y operativas. El artefacto más importante que surge de la etapa de análisis se conoce como especificación de requisitos software (ERS). En la actualidad existen diversas modelos o formas para definir y documentar requisitos, todas ellas se encaminan hacia el mismo objetivo. El siguiente gráfico ilustra las tareas que debe realizarse sin importar el modelo utilizado. 5
Etapas para realizar la captura y análisis de requisitos
El proceso de solución del problema y la solución de éste Para resolver el problema el programador además de la etapa de análisis debe seguir las etapas de diseño y construcción de la solución. Por su parte, el proceso de diseño permite describir los aspectos del sistema a construir antes de que inicie el proceso de fabricación. En esta etapa se contemplan los requisitos identificados en el análisis y da como resultado un plano del software que incluye “la estructura de la solución, sus 1 partes y relaciones”. En esta etapa se fomenta la calidad del proyecto, pues permite plasmar con precisión los requerimientos del cliente. La siguiente etapa es el proceso de construcción de la solución, ésta considera la creación del código fuente, el cual debe ser compilado para producir un código ejecutable, que posteriormente será instalado en el computador del usuario para que este pueda utilizarlo. El programador debe asegurarse de que el sistema funcione de acuerdo a los requisitos obtenidos del análisis. Es importante que se realice la documentación del código, la realización del manual de usuario, y posiblemente de un manual técnico que facilite realizar mantenimientos futuro y ampliaciones al sistema. La solución proporcionada al cliente debe ser evaluada través de las siguientes dimensiones: Evaluación operacional: analiza criterios como facilidad de uso, tiempo de respuesta, reportes en los que se muestra la información Impacto organizacional: eficiencia en el desempeño de los empleados, velocidad en el flujo de información, beneficios en finanzas. Evaluación del proceso de desarrollo, para valorar las herramientas y métodos seguidos durante el desarrollo del proyecto, al igual que la concordancia entre el esfuerzo y tiempo invertidos con el presupuesto destinado y criterios administrativos que se hayan contemplado. Finalmente, la realización de pruebas permite verificar si el software entregado al cliente funciona correctamente y si cumple con los requisitos funcionales especificados. En caso de detectar falencias es necesario realizar las correcciones que garanticen su buen funcionamiento. Es importante resaltar que el proceso de resolver un problema mediante el uso de un computador conduce a la creación de un programa y a la ejecución del mismo. Para construirlo es necesario hacer uso de un lenguaje de programación. Hoy en día existen muchos lenguajes de programación pero la tendencia actual es el uso de lenguaje orientados a objetos. La programación orientada a objetos o POO es un paradigma de programación que pretende simular el mundo real haciendo
1
Fundamentos de Programación, Jorge Villalobos y Ruby Casallas 6
uso de objetos. A continuación se dan algunos conceptos introductorios, antes de iniciar con la construcción de casos de estudio.
1.3. Entidades o clases
El mundo real está lleno de objetos (concretos o abstractos), por ejemplo una persona, un carro, un triangulo. Los cuales se pueden agrupar y abstraer en una clase. Una clase es una plantilla para fabricar objetos, por lo tanto, un objeto es una instancia de una clase. Las instancias de las clases (objetos) se comunican enviándose mensajes. Un programa está compuesto por una o varias clases. Una clase define atributos, es decir, propiedades o características. También define un comportamiento. Un comportamiento es algo que un objeto puede realizar.
1.4. Atributos
Las propiedades reciben el nombre de atributos. Un atributo es una característica de una clase. Una clase puede contener varios o ningún atributo. Por convención el nombre de un atributo comienza con una letra minúscula, pero si el nombre es compuesto se debe iniciar cada palabra con mayúscula, a excepción de la primer palabra que comenzará en minúscula. Cada atributo tiene un nombre y un tipo de dato asociado. Java ya trae definidos algunos tipos de datos. No obstante el usuario podrá crear nuevos tipos dependiendo de sus necesidades. Los tipos de datos que proporciona son:
Enteros
Se usan para representar enteros con signo. Los enteros no poseen números decimales. Un ejemplo de este tipo de datos es la edad de una persona, la cantidad de habitantes de una casa, el número de goles anotados en un partido. Existen cuatro tipos de enteros: byte, short, int y long. Nombre
Rango de valores
byte short int
-128 a 127 -32768 a 32767 -2147483648 a 2147483647 -9223372036854775808 a 9223372036854775807
long Reales
Tamaño en bits 8 16 32 64
Declaración en Java byte var1; short var2; int var3; long var4;
Los reales permiten almacenar números muy grandes que poseen parte entera y parte decimal. Java soporta dos tipos de coma flotante: float y double. Es importante tener en cuenta que en Java cualquier decimal, por defecto, se almacena en un double. Por lo cual, la siguiente instrucción arroja un fallo de compilación: float temperatura=30.6; Este problema puede solucionarse dos formas:
7
- Agregar una f para especificar que el dato asignado será float. float temperatura= 30.6f; - Casting explícito (conversión forzosa) a float para evitar el fallo de compilación float temperatura= (float) (30.6);
Caracter
Nombre
Rango de valores
float double
3,4E-38 a 3,4E38 1.7E-308 a 1.7E308
Tamaño en bits 32 64
Declaración float num1 = 2.7182f; double num2 = 2.125d;
Java usa la codificación Unicode que le permite trabajar con los caracteres de todos los idiomas. Sus primeros 127 caracteres corresponden a los del código ASCII. Un tipo de dato carácter es un único carácter encerrado entre comillas simples. Ejemplos de caracteres „A‟ „H‟ „\b‟ „\n‟ \n newline, a parte \t tab \b backspace, borra a la izquierda \\ es el carácter backslash \' comilla \" comillas
booleano
Nombre
Rango de valores
char
0 a 65536 (Caracteres alfanuméricos)
Declaración
16
chard letra = ‟a‟;
Un dato de tipo booleano puede tomar solo dos valores true o false. Ejemplo: boolean correcto Nombre boolean
String
Tamaño en bits
Rango de valores true, false
Declaración e inicialización boolean bandera = false;
En Java para expresar una cadena (conjunto de caracteres) se utiliza una estructura llamada String. Toda cadena se debe encerrar entre comillas dobles. Un String NO es un tipo de dato primitivo. Ejemplos de String String saludo=“Hola a todos”; String nombre=“Maria Perez”; String saludo=“”; //Aquí se crea un String sin caracteres
8
ACTIVIDAD 1. Para las siguientes clases identifique de qué tipo son los atributos mostrados. Coloque a la derecha dentro del paréntesis el número apropiado y la declaración correcta.
a) Casa Atributo 1) direccion 2) fichaCatastral 3) cantidadCuartos 4) cantidadBanios
Tipo ( 3 ) int ( ) String ( ) String ( ) int
Declaración en Java int cantidadCuartos;
Tipo ( ) double ( ) String ( ) int ( ) int
Declaración en Java
b) Producto Atributo 1) nombre 2) tipoProducto 3) cantidadExistencias 4) precio
tipoProducto puede tomar los siguientes valores: 1 equivale a Papelería 2 equivale a Juguetería 3 equivale a Droguería. c) Persona Atributo 1) nombre 2) estadoCivil 3) edad 4) correoElectronico 5) fechaNacimiento (dd-mmaaaa)
Tipo ( ) int ( ) String ( ) String ( ) String ( ) boolean
Declaración en Java
Tipo ( ) double ( ) String ( ) String ( ) double
Declaración en Java
d) Puerta Atributo 1) Ancho 2) Alto 3) Color 4) Material
2. Dados los siguientes objetos identifique los atributos correctos. 9
a) Empleado nombre, dirección, salario, nota1, nota2, notaDefinitiva nombre, dirección, salario, fechaIngresoEmpresa, fechaNacimiento nombreProducto, codigoProducto, cantidadExistencias nombre, dirección, cantidadHijos b) Zapato talla, color, material, tipo tipoJuguete, marcaJuguete, precio modelo, numeroMotor, placa numero, modelo, tonoDeTimbre, cámara, numTeclas, listadoContactos
1.5. Comportamiento Un comportamiento u operación es algo que un objeto puede realizar. Es importante tener en cuenta que el comportamiento se define en la clase (a través de métodos) pero es el objeto quien lo realiza. Por ejemplo: Si se tiene la clase Baldosa se puede decir que sus atributos son: largo y ancho y que uno de sus métodos es: calcularArea(). Sería incorrecto por ejemplo un método pegarBaldosa, pues esto no lo puede hacer la baldosa sino el constructor. Si se tiene la clase Licuadora se puede decir que sus atributos pueden ser marca, modelo, numeroSerie, capacidad. Sus operaciones (métodos) pueden ser: licuar, partirHielo. Al igual que los atributos, el nombre de un método debe iniciar con minúscula.
ACTIVIDAD Con base en la definición proporcionada con anterioridad llene la siguiente tabla. Especifique los atributos y los métodos: Para la clase Carro los atributos y los métodos serían: ATRIBUTOS C A R R O
1. 6.
2. 7.
1. 6.
2. 7.
3. 8. MÉTODOS 3. 8.
Para la clase Gallina:
10
4. 9.
5. 10.
4. 9.
5. 10.
G A L L I N A
ATRIBUTOS 1. 6.
2. 7.
3. 8. MÉTODOS
4. 9.
5. 10.
1. 6.
2. 7.
3. 8.
4. 9.
5. 10.
Es importante tener claro que clase no es lo mismo que un objeto. Una entidad es simplemente un molde y un objeto es una descripción completa de una clase (en lenguaje técnico a esto se llama instancia). Para representar una clase en UML se requiere de tres secciones, la primera de ellas es el nombre de la clase, la segunda la lista de atributos y finalmente las operaciones. Tal como puede verse a continuación: Baldosa instanciar miBaldosa: Baldosa
largo = 3 ancho = 5
instanciar
largo ancho fijarLargo () fijarAncho () calcularArea ()
miBaldosa1: Baldosa
lado = 9 ancho = 7
instanciar calcularArea() miBaldosa2: Baldosa
lado = 3 ancho = 5
Tres objetos Baldosa que se crean a partir de la clase Baldosa
Es importante anotar, que aunque el estado de miBaldosa es idéntico al de miBaldosa2, cada objeto tiene una identidad la cual es única.
11
Lavadora
instanciar
instanciar miLavadora: Lavadora
marca capacidad modelo serie
= = = =
“LG” 15 MLG5 XY5iJ
marca capacidad modelo serie
fijarMarca() fijarCapacidad() fijarModelo() fijarSerie()
miLavadora1: Lavadora
marca capacidad modelo serie
= = = =
“Samsung” 25 MYG5 XY5iJQ
Dos objetos Lavadora que se crean a partir de la clase Lavadora
ACTIVIDAD A continuación se proporcionan una serie de atributos y dos diagramas de clases. Debe ubicar cada atributo en el diagrama correspondiente e instanciar. nombre, codigoIsbn, cedula, cantidadPaginas, codigoAutor, email, direccion
Persona instanciar
instanciar
miPersona2: Persona
miPersona: Persona
12
Libro instanciar
instanciar
miLibro2: Libro
miLibro: Libro
Cada atributo tiene asociado un tipo de dato. Un tipo de dato es el rango de valores que puede tomar durante la ejecución del programa. Ello implica que si se da un valor fuera del conjunto se producirá un error.
1.5.1. Caso de estudio 1 Unidad I: El estudiante Se desea crear una aplicación para manejar la información de un estudiante. Un estudiante tiene un código, un nombre y dos notas parciales. Se debe permitir crear un nuevo estudiante, calcular la nota definitiva (promedio aritmético de las dos notas parciales) y devolver el código del estudiante.
13
1.5.2.
Comprensión del problema
a) Requisitos funcionales NOMBRE R1 – Crear un nuevo estudiante RESUMEN Permite crear un nuevo estudiante ENTRADAS codigo, nombre, nota1 y nota2 RESULTADOS Un nuevo estudiante ha sido creado NOMBRE R2 – Calcular la nota definitiva RESUMEN Se calcula como el promedio aritmético de las dos notas parciales ENTRADAS Ninguna RESULTADOS La nota definitiva
NOMBRE R3 – Devolver el código del estudiante RESUMEN Permite devolver el código del estudiante ENTRADAS Ninguna RESULTADOS Él código del estudiante
b) El modelo del mundo del problema Son varias las actividades que se deben realizar para construir el modelo del mundo del problema. Identificar las entidades o clases. Para identificarlas, lo primero que debe hacer es resaltar los nombres o sustantivos. Normalmente se convierten en clases o atributos. “Se desea crear una aplicación para manejar la información de un estudiante. Un estudiante tiene un código, un nombre y dos notas parciales. Se debe permitir crear un nuevo estudiante, calcular la nota definitiva (promedio aritmético de las dos notas parciales) y devolver el código del estudiante.”
ENTIDAD DEL MUNDO Estudiante
DESCRIPCIÓN Es la entidad más importante del mundo del problema.
Se descarta código, un nombre y dos notas parciales puesto que son posibles atributo de la clase Estudiante. Identificar los métodos. Para ello se deben resaltar los verbos. El nombre de los métodos debe ser un identificador válido en Java, éste debe ser mnemotécnico, iniciar en verbo y en minúscula. Si está compuesto por dos palabras, entonces la primera palabra irá en minúscula y la inicial de la segunda en mayúscula, por ejemplo determinarExistenciaEstudiante() sería un nombre válido.
14
Recuerde el enunciado del caso de estudio: “Se debe permitir crear un nuevo estudiante, calcular la nota definitiva (promedio aritmético de las dos notas parciales) y devolver el código del estudiante.”
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA ESTUDIANTE ATRIBUTO codigo nombre nota1 nota2
VALORES POSIBLES Cadena de caracteres Cadena de caracteres Valor real positivo Valor real positivo
Tipo de dato String String double double
IDENTIFICACIÓN DE MÉTODOS (para crear un estudiante se debe fijar cada uno de los atributos codigo, nombre, nota1 y nota2) fijarCodigo() fijarNombre() fijarNota1() fijarNota2() (para calcular la nota definitiva se requiere un método que haga el promedio de las dos notas) calcularDefinitiva() (para devolver el código se requiere un método que devuelva el código del estudiante) devolverCodigo() Nota: Todo método lleva paréntesis. Dentro de los paréntesis pueden o no ir parámetros. Un parámetro es todo aquello que se necesita para resolver un problema y que no pertenece al objeto. Los parámetros están relacionados con las variables de entrada que se identificaron cuando se obtuvieron los requisitos funcionales. Por ahora, dado que se está introduciendo apenas el tema de identificación de métodos, se omitirán los parámetros, pues lo importante es determinar las operaciones que el objeto realiza.
3. Las Relaciones entre las clases del mundo En este punto es importante familiarizarse con el concepto de diagrama de clases. “Un diagrama de clases describe los tipos de objetos que hay en el sistema y las diversas clases de relaciones estáticas que existen entre ellos. Hay dos tipos principales de relaciones estáticas: las 2 asociaciones y los subtipos (un profesor es un empleado).” Este material solo hará uso de las asociaciones. Es importante identificar las relaciones entre las clases para luego proceder a asignarle un nombre. Para indicar que existe una relación se hará uso de una línea con flechas en uno de sus extremos. El nombre de la asociación debe dejar claro que una entidad utiliza a otra clase como parte de sus atributos o características. Se debe tener en cuenta que entre dos clases puede existir más de una relación. Antes de continuar el lector debe tener claro, que las clases se guardarán en carpetas especiales llamadas paquetes, dependiendo del tipo de clase que se vaya a definir. Si se crea una interfaz 2
Fowler, Martin y Scott, Kendall 15
gráfica esta clase se almacenará en un paquete llamado interfaz. Por el contrario, si se crea una clase del mundo real, que contenga la parte lógica se almacenará en un paquete llamado mundo. A continuación se construirá un diagrama de clases que permita visualizar las relaciones de los elementos involucrados en el mundo del problema, con lo cual se ve claramente un modelo conceptual.
Métodos identificados fijarCodigo() fijarNombre() fijarNota1() fijarNota2() calcularDefinitiva() devolverCodigo()
Nombre en el diagrama de clases setCodigo(String codigo) setNombre(String nombre) setNota1(double nota1) setNota2(double nota2) calcularDefinitiva() getCodigo()
Observe que a cada uno de los métodos fijar que se identificaron previamente, cuando se les puso el nombre apropiado para trabajarlos en el diagrama de clases, se les colocó un parámetro, el cual tiene el mismo nombre de la variable que se desea inicializar. Por ejemplo, si se requiere fijar el código, entonces el método setCodigo debe llevar un parámetro, que en nuestro caso se llama también codigo. Lo mismo ocurre con el método setNombre, el cual tiene un parámetro llamado nombre. Por sencillez, es importante que tenga claro que todo método set lleva un parámetro, al cual se le pondrá el mismo nombre de la variable que se desea inicializar. Es de anotar, que el nombre que se le coloque al parámetro puede ser diferente, lo realmente importante es que exista una coincidencia en tipo de dato, más no en nombre. No obstante, en este material el parámetro de cada método set llevará el mismo nombre de la variable que pretende inicializar.
16
Como se explicó con anterioridad por cada método set debe ir un parámetro. Al mirar la interfaz de este caso de estudio se puede observar que para poder crear el estudiante, el usuario debe ingresar cuatro datos, a saber: codigo, nombre, nota1 y nota2 antes de que se presione el botón guardar. Esta información debe capturarse para poderla utilizar posteriormente. Tenga en cuenta que crear el estudiante no solo implica reservarle un espacio en la memoria sino también almacenar la información que el usuario digita. Si la información no se almacena todo se perdería. Un ejemplo de la vida real que nos permite hacer una analogía con lo anterior es el siguiente: Un docente quiere conformar un directorio de números telefónicos de todos sus estudiantes. Cada estudiante se acerca al docente y le da sus datos, pero el docente no registra la información en su libreta. Al final la libreta del docente queda vacía.
Ahora bien, se dijo previamente que se requería de los métodos: setCodigo(String codigo), setNombre(String nombre), setNota1(double nota1), setNota2(double nota2), calcularDefinitiva() y getCodigo(). Cada uno de estos métodos se ejecuta dependiendo del botón que el usuario presione, tal como se muestra en el siguiente gráfico.
getCodigo()
setCodigo(String codigo) setNombre(String nombre) setNota1(double nota1) setNota2(double nota2)
calcularDefinitiva()
- Cuando se presiona el botón guardar se debe reservar memoria al estudiante y posteriormente capturar el código, el nombre, la nota 1 y la nota2. Se debe almacenar el código que el usuario digita en la ventana, este es el motivo por el cual el método setCodigo tiene un parámetro. Igual ocurre con el nombre, la nota1 y la nota2. - Si se presiona el botón “Definitiva” es porque previamente ya se ha ingresado la información, es decir; el código, el nombre, la nota1 y la nota2; por ello no se requiere que el usuario ingrese información adicional a la que ya se encuentra almacenada. Este el motivo por el cual el método calcularDefinitiva no lleva parámetros 17
- Si se presiona el botón “Código”, es porque previamente ya se ha ingresado la información, por ello no se requiere que el usuario ingrese información adicional a la que ya se encuentra almacenada. Este el motivo por el cual el método getCodigo no lleva parámetros
1.5.3. Caso de estudio 2 Unidad I: El empleado Se desea crear una Aplicación para manejar la información de un Empleado. Un empleado tiene un nombre, una cedula, una dirección y un salario asignado. La aplicación debe permitir crear un nuevo empleado Incrementar el salario en un 10% Decrementar el salario en un porcentaje dado por el usuario Devolver la dirección del empleado
1.5.4.
Comprensión del problema
a) Requisitos funcionales NOMBRE R1 – Crear un nuevo empleado RESUMEN Permite crear un nuevo empleado ENTRADAS nombre, cedula, dirección, salario RESULTADOS Un nuevo empleado ha sido creado 18
NOMBRE R2 – Incrementar salario RESUMEN Permite incrementar el salario en un 10% ENTRADAS Ninguna RESULTADOS El salario incrementado
NOMBRE R3 – Decrementar salario RESUMEN Permite decrementar el salario en un porcentaje dado por el usuario ENTRADAS El porcentaje RESULTADOS El salario decrementado
NOMBRE RESUMEN ENTRADAS Ninguna RESULTADOS La dirección
R4– Devolver la dirección Devuelve la dirección que el usuario ingreso previamente
b) El modelo del mundo del problema Las actividades que se deben realizar para construir el modelo del mundo son las siguientes: Identificar las entidades o clases.
ENTIDAD DEL MUNDO Empleado
DESCRIPCIÓN Es la entidad más importante del mundo del problema.
Identificar los métodos. Para ello se deben resaltar los verbos. La aplicación debe permitir crear un nuevo empleado Incrementar el salario en un 10% Decrementar el salario en un porcentaje dado por el usuario Devolver la dirección del empleado
19
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA EMPLEADO ATRIBUTO nombre cedula direccion salario
VALORES POSIBLES Cadena de caracteres Cadena de caracteres Cadena de caracteres Valor real positivo
Tipo de dato String String String double
IDENTIFICACIÓN DE MÉTODOS (para crear un Empleado se debe fijar cada uno de los atributos nombre, cedula, dirección y salario) fijarNombre(String nombre) fijarCedula(String cedula) fijarDireccion (String direccion) fijarSalario (double salario)
(para incrementar el salario en un 10% se requiere de un método que calcule el incremento) incrementarSalario() (Se requiere un método para decrementar el salario en un porcentaje dado por el usuario) decrementarSalarioP(double porcentaje) (Se requiere un método para devolver la dirección del empleado) devolverDireccion()
Las Relaciones entre las clases del mundo Métodos identificados fijarNombre(String nombre) fijarCedula(String cedula) fijarDireccion(String direccion) fijarSalario(double salario) incrementarSalario() decrementarSalarioP(double porcentaje) devolverDireccion()
Nombre en el diagrama de clases setNombre(String nombre) setCedula(String cedula) setDireccion(String direccion) setSalario(double salario) incrementarSalario() decrementarSalarioP(double porcentaje) getDireccion()
El diagrama de clases correspondiente es:
20
1.6. Hoja de trabajo 1 Unidad I: La granja
Un granjero requiere de una aplicación que le permita calcular la cantidad de metros de cable que debe comprar para cercar su finca. La finca del granjero tiene la siguiente forma.
lado2
lado 1
lado2 El granjero conoce la longitud en metros de algunos de los linderos de su finca (lado1 y lado2), pero existe un área de la cual no sabe las medidas exactas, la única información con la que cuenta es que es una zona triangular (específicamente un triangulo isósceles).
El granjero solicita que se proporcione además de la cantidad de metros necesarios para cercar, el área total de su finca.
21
1.6.1.
Comprensión del problema
a) Requisitos funcionales NOMBRE R1 – RESUMEN ENTRADAS lado 1 y lado 2 RESULTADOS
NOMBRE RESUMEN ENTRADAS
R2 –
RESULTADOS
NOMBRE RESUMEN ENTRADAS
R3 –
RESULTADOS
b) El modelo del mundo del problema Las actividades que se deben realizar para construir el modelo del mundo son las siguientes: Identificar las entidades o clases. ENTIDAD DEL MUNDO Finca
DESCRIPCIÓN Es la entidad más importante del mundo del problema.
Identificar los métodos. Para ello se deben resaltar los verbos.
22
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA Finca ATRIBUTO lado 1 lado 2 lado 3
VALORES POSIBLES Valor real positivo Valor real positivo Valor real positivo IDENTIFICACIÓN DE MÉTODOS
Tipo de dato double double double
(para crear una Finca se debe fijar cada uno de los atributos conocidos) fijarLado1(double lado1) fijarLado2(double lado2) (Se debe crear un método para calcular el valor del lado3) inicializarLado3 (Se requiere un método para calcular el perímetro de la finca) calcularPerimetro (Se requiere un método para calcular el Area) calcularArea
3. Las Relaciones entre las clases del mundo Métodos identificados fijarLado1(double lado1) fijarLado2(double lado2) inicializarLado3() calcularPerimetro() calcularArea()
Nombre en el diagrama de clases setLado1(double lado1) setLado2(double lado2) inicializarLado3() calcularPerimetro() calcularArea()
23
Actividad Construya el diagrama de clases para el caso de estudio de la finca
1.7. Hoja de trabajo 2 Unidad I: La Constructora
Una constructora requiere una aplicación que le permita detectar la cantidad baldosas y de cajas requeridas para cubrir una superficie cuadrada. El constructor conoce los lados del piso y las dimensiones de cada baldosa. La baldosa no se vende se forma individual, solo por cajas y cada caja esa compuesta por 10 baldosas.
1.7.1.
Comprensión del problema
a) Requisitos funcionales NOMBRE RESUMEN ENTRADAS
R1 –
RESULTADOS
24
NOMBRE RESUMEN ENTRADAS
R2 –
RESULTADOS
NOMBRE RESUMEN ENTRADAS
R3 –
RESULTADOS
b) El modelo del mundo del problema Las actividades que se deben realizar para construir el modelo del mundo son: Identificar las entidades o clases. ENTIDAD DEL MUNDO Piso Baldosa
DESCRIPCIÓN Es la entidad más importante del mundo del problema. El piso está formado por baldosa. Cada una posee unas dimensiones.
Para identificar los métodos se deben resaltar los verbos.
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA Baldosa ATRIBUTO VALORES POSIBLES Tipo de dato
IDENTIFICACIÓN DE MÉTODOS
25
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA Piso ATRIBUTO
VALORES POSIBLES
Tipo de dato
IDENTIFICACIÓN DE MÉTODOS
Las Relaciones entre las clases del mundo Métodos identificados para Baldosa
Nombre en el diagrama de clases
Métodos identificados para Piso
Nombre en el diagrama de clases
Construya el diagrama de clases
26
1.8. Métodos Los métodos permiten definir el comportamiento de los objetos que se crean con una clase. Un método es un conjunto de instrucciones que permiten resolver un problema particular. Está formado por un tipo de acceso, un tipo de retorno, un nombre, unos parámetros (si son necesarios) y un listado de instrucciones. La estructura general de un método es la siguiente: tipoDeAcceso tipoRetorno nombreDelMetodo( parámetros ){ listado de instrucciones } El tipo de acceso indica la visibilidad del método para las clases externas, existen 4 tipos de accesos, a saber: private: Indica que el método solo puede ser utilizado en el interior de la clase en la que se encuentra definido public: Permite que el método sea utilizado desde cualquier clase. protected: Indica que el método sólo puede accederse desde su mismo paquete y desde cualquier clase que extienda (es decir que herede) la clase en la cual se encuentra, sin importar si está o no en el mismo paquete. Es de anotar que la herencia no se tratará en libro. Si no se especifica un modificador se asume el nivel de acceso por defecto, el cual consiste en que el método puede ser accedido únicamente por las clases que pertenecen al mismo paquete. Un paquete puede verse como una carpeta a través de la cual es posible agrupar clases con características comunes. La siguiente tabla resume los modificadores: La misma clase
Otra clase del mismo paquete
Subclase de otro paquete
Otra clase de otro paquete X
private
X
public
X
X
X
protected
X
X
X
default
X
X Modificadores de acceso
Es de anotar que los métodos construidos en este material llevarán el modificador public y los atributos private. Por otra parte, el nombre del método debe ser un identificador válido en Java, éste debe ser mnemotécnico y tener correspondencia con lo que hace. También debe iniciar en verbo y en minúscula. Si está compuesto por dos palabras, entonces la primera palabra irá en minúscula y la inicial de la segunda en mayúscula. El retorno indica el tipo del resultado por ejemplo en el caso de calcularNotaDefinitiva el retorno sería double, es decir se devolvería un número con decimales que corresponde a la nota definitiva. Un método Java puede retornar un tipo de dato primitivo o una referencia a un objeto Si el método tiene retorno debe especificarse claramente el tipo de dato devuelto y debe incluirse la sentencia return para realizar dicha tarea.
27
Si el método no devuelve un valor, se debe poner void como tipo de retorno y no puede utilizarse return. Los parámetros son los datos necesarios para resolver el problema y que no pertenecen al objeto. Una operación debe ser simple y cohesiva, por lo cual es importante que use al menos uno de los atributos definidos en la clase. Es importante distinguir los términos parámetro y argumento. Un parámetro es una variable definida por un método y que recibe un valor cuando se llama a ese método. Un argumento es un 3 valor que se pasa a un método cuando éste es invocado” . Por ejemplo, sumarEnteros( 6, 5) pasa los valores 6 y 5 como argumentos. Dentro de un método pueden ir múltiples instrucciones, ya sea declaraciones de variables locales, expresiones, estructuras de decisión o repetitivas (estas últimas se tratarán en unidades siguientes). Dependiendo de la función que realice un método, éste puede clasificarse en uno de los siguientes tipos: Métodos modificadores: Son los encargados de cambiar el estado del objeto Métodos analizadores: permiten calcular información apoyándose en la información con la que cuentan los objetos de la clase Métodos constructores: Su objetivo es inicializar los atributos de un objeto en el momento mismo de su creación. Métodos accesores o getter‟s: Permiten devolver el valor de un campo privado, es decir, un atributo de un objeto.
1.8.1.Expresiones Una expresión es una combinación de variables, constantes y/o operadores. Java dispone de los siguientes operadores: - Operadores aritméticos Los operadores aritméticos permiten realizar operaciones aritméticas. Entre ellos se encuentran + (suma), - (resta), * (multiplicación), / (división), % (módulo, residuo de la división), incremento y decremento. En lo referente al operador división es importante tener en cuenta que la división entre enteros da como resultado otro entero. Por ejemplo:
int a = 40; int b = 6; double resultado = ( a + b ) / 3; El programa debería arrojar 15.333 pero da 15. Para corregir dicho error se pueden aplicar las siguientes soluciones: double resultado = ( a + b ) / 3.0;
3
Gómez, Carlos Eduardo y Gutiérrez, Julián Esteban 28
ó double total = a + b; double resultado = total / 3; El siguiente ejemplo ilustra el uso del operador módulo int a=8, b=5; int residuo=a%b; La variable residuo queda con el valor de 3. Por otra parte, los operadores incremento o decremento permiten incrementar o decrementar las variables en una unidad. Por ejemplo:
int a=8, b=5; int c=0; a++; b+=2; c=a+b; Según el código anterior, la variable a queda con un valor de 9, la variable b finaliza con 7 y la variable c con 16. Ahora observe el siguiente ejemplo: int p = 1 , q =0, k=0 ; q = p++; k = ++p; En el caso anterior, a q se le asigna el valor de p y a continuación la p se incrementa en 1, con lo cual q será igual a 1 y p igual a 2. En la instrucción siguiente, la p se incrementa antes de efectuarse la asignación, es decir queda valiendo 3, dicho valor es asignado a la variable k, quien también queda valiendo 3.
- Operadores lógicos Los operadores lógicos dan un resultado de tipo booleano. De igual forma sus operandos son también valores lógicos. Java proporciona 3 operadores lógicos; dos de ellos binarios (And y or) y uno unario (negación). Operador Significado && AND || OR ! NOT Operadores lógicos El operador && da como resultado true si los dos operandos tienen el valor de true. De lo contrario genera un resultado false.
29
operando1 false false true true
Operador operando2 false && true && false && true && Operador AND
salida false false false true
Un ejemplo de uso del operador anterior es el siguiente La variable operando1 corresponde a tarjetaDeCredito y operando2 corresponde a clave. La siguiente línea false
false
&&
false
Se puede interpretar como: Una persona va al cajero, no lleva a tarjeta y no conoce la clave entonces no puede hacer nada. La línea: false
true
&&
false
Indicaría que la persona fue al cajero, no llevaba tarjeta pero si sabía la clave, por lo tanto no pudo hacer nada. En conclusión solo si la persona lleva la tarjeta y conoce la clave podrá retirar dinero. Por otra parte, el operador || da como resultado true si alguno de sus operandos es true.
Operando 1 false false true true
Operador || || || ||
Operando 2 false true false true
Salida false true true true
Operador OR Un ejemplo del funcionamiento del operador anterior podría ser un buscador de libros. El cual permita encontrar publicaciones que contengan cualquiera o todos los términos especificados. Por ejemplo se podría asumir que el operando1 es tituloConPalabraPerro y el operando2 es títuloConPalabraGato, si se utiliza el operador || buscaría todos los libros en la biblioteca que contengan en su titulo el primer o segundo término o ambos. Otro ejemplo sería un buscador de archivo en al cual se le dan dos carpetas para buscar el archivo. El archivo puede encontrarse en la carpeta 1 o en la carpeta 2, o en las dos carpetas. No obstante existe la posibilidad de que no se encuentre en ninguna de las dos carpetas.
Finalmente, el operador ! (negación) da como resultado false si al evaluar su único operando el resultado es true y devuelve true en caso contrario. Ejemplo: Se tiene la siguiente variable: boolean sexo= true;
30
Si se asume que true es mujer, entonces la siguiente instrucción cambiará el valor de la variable sexo a hombre. sexo=!sexo; Otro ejemplo podría ser: boolean mayorDeEdad= false; En este caso la variable mayor de edad está inicializada en false, lo cual representa que la persona es menor de edad. Si se efectúa la siguiente instrucción: mayorDeEdad=!mayorDeEdad; entonces la persona se convirtió en mayor de edad.
- Operadores relacionales Permiten comparar valores, su resultado es de tipo lógico. Entre ellos se encuentran:
== (igualdad) != (diferente) (mayor que) < (menor que) >= (mayor o igual) <= (menor o igual)
- Operador de concatenación con cadena de caracteres '+': Un ejemplo de uso de este operador es el siguiente: double result=40.5; System.out.println("El total es"+ result +"unidades"); La anterior instrucción imprime: “El total es 40.5 unidades”
31
ACTIVIDAD
1) Determine los valores finales para todas las variables utilizadas en la siguiente porción de código a) int a=56, b=-4, c=23, d=45, e=23, f, g, h; f= (a*d) - b; g= c+d+e; h= 67- a/c; f=h*g-a; g=g-h; Opciones de respuesta A) a: 57 , b: -3, c: 23, d: 44, e: 23, f: 5859, g: 26, h: 65 B) a: 56 , b: -4, c: 23, d: 45, e: 23, f: 5859, g: 26, h: 65 C) a: 65 , b: -4, c: 23, d: 45, e: 23, f: 5859, g: 26, h: 65 D) a: 56 , b: -4, c: 25, d: 45, e: 23, f: 5859, g: 27, h: 65
b) char estadoCivil= 'A'; int edad=18; String nombre="Pepe",apellido="Pelaez", nombreCompleto=" "; int nivelEstudios=2; /*0 indica bachiller, 1 pregrado, 2 especializacion, 3 maestria y 4 doctorado*/ nivelEstudios++; nombreCompleto=nombre+ " "+apellido; edad--; estadoCivil=(char)(estadoCivil+1); A) estadoCivil= B edad= 17 nombreCompleto= Pelaez Pepe nivelEstudios= 3 B) estadoCivil= A edad= 17 nombreCompleto= Pepe Pelaez nivelEstudios= 3 c) estadoCivil= B edad= 17 nombreCompleto= Pepe Pelaez nivelEstudios= 3 d) estadoCivil= B edad= 17 nombreCompleto= Pepe Pelaez nivelEstudios= 13 c) Dadas las siguientes instrucciones determine el resultado: int edad=18; double salario=350000; char estadoCivil='S'; int cantidadDeHijos=2; boolean cabezaDeHogar=true; boolean mayorDeEdad=false; double subsidioUnitario=80000; Instrucción edad>=18 cabezaDeHogar ¡= true && cantidadHijos!=0 && estadoCivil==‟S‟ double subsidio=cantidadHijos*subsidioUnitario; subsidio>300000
Resultado a)true a)true
b) false b) false
a)true
b) false
32
(!(mayorDeEdad==true && salario< 700000)) || (cantidadDeHijos%2==0)
a)true
b) false
d) Consulte en internet las instrucciones que deben escribirse para saber si un año es bisiesto y seleccione la opción correcta. A) ((( año % 4 == 0 ) && ( año % 100 != 1 )) || ( año % 400 == 0 )) B) ((( año % 4 == 1 ) && ( año % 100 == 0 )) || ( año % 400 == 0 )) C) ((( año % 4 == 0 ) && ( año % 100 != 0 )) || ( año % 400 != 0 )) D) ((( año % 4 == 0 ) && ( año % 100 != 0 )) || ( año % 400 == 0 ))
1.8.2.Cómo construir un método La construcción de un método incluye los siguientes pasos: Identificar el tipo de retorno Definir la signatura del método. La signatura de un método está compuesta por el nombre del método, los tipos de los parámetros y el orden de éstos). Se debe tener claro que los modificadores usados y el tipo devuelto no forman parte de la signatura del método. Agregar las instrucciones dentro de él. Para ilustrar lo anterior se procederá a retomar el caso de estudio 1: Se desea crear una aplicación para manejar la información de un estudiante. Un estudiante tiene un código, un nombre y dos notas parciales. Se debe permitir crear un nuevo estudiante, calcular la nota definitiva (promedio aritmético de las dos notas parciales) y devolver el código del estudiante. El diagrama de clases construido que se construyó fue:
Para poder iniciar la construcción de los métodos se deben tener muy claros cuáles son los atributos y adicionalmente el concepto de parámetro: Los parámetros son los datos necesarios para resolver el problema y que no pertenecen al objeto.
33
El primer método que se va a construir es calcularDefinitiva. Se sabe que se va a calcular la nota promedio, por lo cual el retorno será de tipo double. El siguiente paso es colocar el nombre del método y abrir un paréntesis. El paréntesis se deja abierto porque es necesario identificar si habrá o no parámetros. public double calcularDefinitiva (…….. Para saber si hay parámetros se debe preguntar si con la información con la que cuenta (codigo, nombre, nota1, nota2) es suficiente o si requiere que el usuario ingrese información adicional. Se sabe que para calcular la nota definitiva basta con promediar la nota1 y la nota2. Por lo tanto se concluye que no se requiere información adicional y por lo tanto no se necesitan parámetros, pues con la información con la que se cuenta es posible realizar el cálculo solicitado. Por lo tanto se puede procede a cerrar el paréntesis y a construir las instrucciones que permitan calcular el promedio. public double calcularDefinitiva (){ double promedio=(nota1+nota2)/2; return promedio; }
Ahora se procederá a construir los métodos modificadores, setter. Recuerde que se debe construir uno por cada atributo (esto cambiará cuando se incorpore el concepto de método constructor). Para construir este tipo de métodos se deben seguir las siguientes reglas: - No llevan retorno, es decir se debe poner void. - Llevan un parámetro, al cual se le pondrá el mismo nombre del atributo que se pretende inicializar. - En su interior llevan una única línea: this.atributo=parámetro. La siguiente tabla ilustra los métodos set para los atributos de la clase Estudiante
set para código void setCodigo( String codigo ) { this.codigo = codigo; } set para nota1 ` void set1Nota( double nota1) { this.nota1 = nota1; }
set para nombre void setNombre( String nombre ) { this.nombre = nombre; } set para nota2 ` void set2Nota( double nota2) { this.nota2 = nota2; }
Finalmente se construyen los métodos get. Para su elaboración se siguen las siguientes reglas: - Llevan retorno, del mismo tipo del atributo al que se le está haciendo el get. - No llevan parámetros - En su interior llevan la instrucción: return atributo;
34
get para código String getCodigo( ) { return codigo; }
Luego de haber construido los métodos se procede a integrar todo en una clase. public class Estudiante { private String codigo, nombre; private double nota1, nota2; public void setCodigo(String codigo) { this.codigo = codigo; } public void setNombre(String nombre) { this.nombre = nombre; } public void setNota1(double nota1) { this.nota1 = nota1; } public void setNota2(double nota2) { this.nota2 = nota2; } public double calcularDefinitiva() { return (nota1+nota2)/2; } public String getCodigo() { return codigo; } } 1.8.3.Declarar variables en Java El sitio donde sea declare una variable determina donde puede ser utilizada. Las posibles ubicaciones se describen a continuación El primer lugar donde se puede declarar una variable es dentro de la clase, pero fuera de los métodos. Este tipo de variables se conocen como atributos de la clase (o variables globales) y pueden usarse dentro de cualquier método contenido en la clase. El segundo lugar es al interior de cualquier método. Se les denomina variables locales y solo pueden utilizarse en instrucciones que estén contenidas en el método en donde se declaran. En tercer lugar se pueden definir como parámetros de un método, en donde luego de recibir valor, se pueden manipular como una variable local en ese método. Se puede concluir entonces que una variable local sólo puede utilizarse dentro del método donde se declara, es decir, solo allí está viva y es desconocida por otros métodos.
35
public class Estudiante {
private String codigo, nombre; private double nota1, nota2;
public double calcularDefinitiva(){
double promedio=0; //Instrucciones para cambiar inicializar el promedio }
public double darBonificacion(double cantidad) { //Instrucciones
} }
1
La guía de laboratorio No.1 describe los pasos para construir las clases del proyecto estudiante en Eclipse
1.8.4.Envío de mensajes o llamado de métodos Cuando se envía un mensaje a un objeto, se le está ordenando que ejecute un método, el cual debió definirse previamente en la clase con la cual fue creado dicho objeto. Por ejemplo cuando se le dice a un objeto estudiante que informe su nota definitiva lo que realmente se está haciendo es pasarle el mensaje “calcularDefinitiva”. Para mandar mensajes a los objetos se utiliza el operador punto. En general para llamar un método, lo que se hace es colocar la referencia al objeto, seguido del operador punto, luego el nombre del método, y finalmente, dentro de paréntesis se pasan los 36
correspondientes argumentos (tantos argumentos como parámetros se hayan puesto al momento de crear el método). Es importante que previamente a la invocación del método haya reservado memoria a través de la instrucción new, esto con el objetivo de evitar que se genere la excepción NullPointerException. NullPointerException aparece cuando se intenta acceder a métodos en una referencia que se encuentra nula, es decir a la cual no se le ha reservado memoria a través de new. En tal caso la llamada al método no es permitida.
2
La guía de laboratorio No.2 describe los pasos para importar un proyecto en Eclipse y construir una interfaz gráfica elemental.
A continuación se muestran las instrucciones necesarias para poder invocar los métodos y mostrar en pantalla los resultados que estos arrojan. Estas instrucciones deben colocarse en la interfaz gráfica. - Se reserva memoria Estudiante miEstudiante=new Estudiante(); - Se lee la información de los campos de texto y se declaran tantas variables como métodos con retorno se hayan hecho. La pantalla que se creó fue la siguiente. En ella hay campos de texto (jTextFields, JButtons y JLabels)
jTextFieldCodigo jTextFieldNombre jTextFieldNota1 jTextFieldNota2.
jButtonGuardar
jButtonDefinitiva
jButtonCodigo jLabelSalida Text
Para que los métodos funcionen es necesario tomar la información de los campos de texto. Las siguientes instrucciones permiten realizarlo.
37
codigo=jTextFieldCodigo.getText(); nombre=jTextFieldNombre.getText(); nota1= Double.parseDouble (jTextFieldNota1.getText()); nota2= Double.parseDouble (jTextFieldNota2.getText());
- Se llama a los métodos set. Primero va la referencia al objeto seguida por el nombre del método y su correspondiente argumento. /*Para crear un Estudiante, además de reservar memoria, se debe fijar cada uno de los atributos: codigo, nombre, nota1, nota2 */ miEstudiante.setCodigo(codigo); miEstudiante.setNombre(nombre); miEstudiante.setNota1(nota1); miEstudiante.setNota2(nota2);
- Se llama a los demás métodos creados. Si el método retorna, el valor que el método devuelve se asigna a un variable del mismo tipo de retorno especificado a la hora de crear el método. Ejemplo: el método calcularDefinitiva() devuelve un double, entonces se declaró una variable de tipo double llamada def para almacenar este resultado. Como este método no tenía parámetros por eso no se le mandaron argumentos. Finalmente, se muestran los resultados en los jLabel o etiquetas creadas para tal fin.
def= miEstudiante.calcularDefinitiva(); jLabelSalida.setText("La nota definitiva es "+def);
- Se repite el proceso con el método getCodigo() cod= miEstudiante.getCodigo(); jLabelSalida.setText("El código del estudiante es "+ cod);
Si desea ejecutar el proyecto sin crear interfaz gráfica siga la guía No. 3
3
Opcional: La guía de laboratorio No.3 describe los pasos para importar un proyecto en Eclipse y ejecutar un proyecto sin construir interfaz gráfica.
ACTIVIDAD Identifique si los siguientes métodos están bien invocados. En caso contrario reescriba las instrucciones para que se ejecuten de forma correcta.
38
Clase y método a analizar
Llamado del método
public class Triangulo { private double base, altura;
double base=5, altura=8, area=0; Triangulo miTriangulo (); miTriangulo.setBase(); miTriangulo.setAltura(altura); area=miTriangulo.calcularArea(base,a ltura);
public void setBase(double base) { this.base = base; } public void setAltura(double altura) { this.altura = altura; } public double calcularArea() { return base*altura; } } public class Cuadrado { private double lado; public void setLado(double lado) { this.lado = lado; }
double lado=4, perimetro=0; Cuadrado miCuadrado = new Cuadrado(); perimetro=miCuadrado.calcularPerimet ro(); calcularPerimetro.miCuadrado(); }
public double calcularPerimetro() {return 4*lado;} public double incrementarPerimetro(int cantidad) { return calcularPerimetro()+cantidad; } }
1.8.5.Solución del caso de estudio 2 A continuación se retomará el caso de estudio2 para proceder a su solución. Se desea crear una Aplicación para manejar la información de un Empleado. Un empleado tiene un nombre, una cedula, una dirección y un salario asignado. La aplicación debe permitir crear un nuevo empleado Incrementar el salario en un 10% Decrementar el salario en un porcentaje dado por el usuario Devolver la dirección del empleado El diagrama de clases que se construyó para esta clase fue el siguiente:
39
Partiendo de este diagrama de clases se iniciará la construcción del código fuente. El primer método que se va a construir es incrementarSalario. Se debe tener claro como se hará el incremento, esto es un 10%. Se sabe que se va a incrementar el salario, por lo cual el retorno será de tipo double. El siguiente paso es colocar el nombre del método y abrir un paréntesis. El paréntesis se deja abierto porque es necesario identificar si habrá o no parámetros. public double incrementarSalario (…….. Para saber si hay parámetros se debe preguntar si con la información con la que cuenta (nombre, cedula, dirección y salario) es suficiente o si requiere que el usuario ingrese información adicional. Se sabe que el incremento será de 10% sobre el salario y se tiene también el salario. Por lo tanto se concluye que no se requiere información adicional y no se necesitan parámetros, pues con la información con la que se cuenta es posible realizar el cálculo solicitado. Por lo tanto se puede procede a cerrar el paréntesis y a construir las instrucciones que permitan calcular el promedio. public double incrementarSalario () { double incremento =salario*0.1; salario=salario + incremento; return salario; }
El siguiente método en el que se trabajará es el que permite decrementar el salario en un porcentaje dado por el usuario. Primero se debe especificar el retorno y nombre del método se debe identificar si tiene parámetros. public double decrementarSalarioP (…….. Para identificar si tiene parámetros se debe preguntar si con la información con la que cuenta (nombre, cedula, dirección y salario) es suficiente o si requiere que el usuario ingrese información adicional. Es claro que en este caso el usuario debe ingresar el porcentaje de decremento, por ello se concluye que el método requiere de un parámetro de tipo double al que se le llamará porcentaje.
40
public double decrementardecrementarSalarioP (double porcentaje) { double decremento =salario*porcentaje/100; salario=salario - decremento; return salario; }
Ahora se procederá a construir los métodos modificadores setter set para direccion public void setDireccion(String direccion) { this.direccion = direccion; } set para salario public void setSalario(double salario){ this.salario = salario; }
set para nombre public void setNombre(String nombre){ this.nombre = nombre; } set para cedula public void setCedula(String cedula){ this.cedula = cedula; }
Finalmente se construyen los métodos get. get para direccion public String getDireccion() { return direccion; } Luego de haber construido los métodos se procede a integrar todo en una clase. public class Empleado { private String nombre, cedula, direccion; private double salario; public void setDireccion(String direccion) { this.direccion = direccion; } public void setNombre(String nombre) { this.nombre = nombre; } public void setCedula(String cedula) { this.cedula = cedula; } public void setSalario(double salario) { this.salario = salario; } public double incrementarSalario () { double incremento =salario*0.1; salario=salario + incremento; return salario; }
41
public double decrementardecrementarSalarioP (double porcentaje) { double decremento =salario*porcentaje/100; salario=salario - decremento; return salario; } public String getDireccion() { return direccion; } } Para poder ejecutar el programa es necesario en la interfaz gráfica: - Reservar memoria private Empleado miEmpleado= new Empleado(); - Se lee la información de los campos de texto y se declaran tantas variables como métodos con retorno se hayan hecho. String nombre=jTextFieldNombre.getText(), cedula=jTextFieldCedula.getText(), direccion=jTextFieldDireccion.getText(); double salario=Double.parseDouble(jTextFieldSalario.getText()); /*Se crearon tres métodos que retornan, por lo tanto se declaran tres variables para que almacenen estos resultados*/ double salarioI=0, salarioD; String dir="";
- Se llama a los métodos set. Primero va la referencia al objeto seguida por el nombre del método y su correspondiente argumento. /*Para crear un Empleado, además de reservar memoria, se debe fijar cada uno de los atributos*/ miEmpleado.setCedula(cedula); miEmpleado.setDireccion(direccion); miEmpleado.setNombre(nombre); miEmpleado.setSalario(salario);
- Se llama a los demás métodos creados. El método incrementarSalario retorna un double y no tiene parámetros. double salarioI= miEmpleado.incrementarSalario(); jLabelSalida.setText("El salario incrementado es "+salarioI);
Ahora se continuará con el método para decrementar el salario. Este método retorna un double y tiene un parámetro, el cual debe ser ingresado por el usuario. double porcentaje=Double.parseDouble(jTextFieldPorcentajeDec.getText()); double salarioD= miEmpleado.decrementardecrementarSalarioP(porcentaje); jLabelSalida.setText("El salario decrementado es "+salarioD);
42
- Se repite el proceso con el método getDireccion dir= miEmpleado.getDireccion(); jLabelSalida.setText("La dirección es: "+dir);
1.8.6.Solución de la hoja de trabajo 1 Recuerde el enunciado de la hoja de trabajo 1: Un granjero requiere de una aplicación que le permita calcular la cantidad de metros de cable que debe comprar para cercar su finca. La finca del granjero tiene la siguiente forma.
lado2
lado1
lado2 El granjero conoce la longitud en metros de algunos de los linderos de su finca (lado1 y lado2), pero existe un área de la cual no sabe las medidas exactas, la única información con la que cuenta es que es una zona triangular (específicamente un triangulo isósceles). El granjero solicita que se proporcione además de la cantidad de metros necesarios para cercar, el área total de su finca. La identificación de atributos y métodos para Finca fue la siguiente:
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA Finca ATRIBUTO lado 1 lado 2 lado 3
VALORES POSIBLES Valor real positivo Valor real positivo Valor real positivo IDENTIFICACIÓN DE MÉTODOS
Tipo de dato double double double
(para crear una Finca se debe fijar cada uno de los atributos conocidos) public void setLado1(double lado1) public void setLado2(double lado2) (Se debe crear un método para calcular el valor del lado3) 43
public void inicializarLado3() (Se requiere un mĂŠtodo para calcular el perĂmetro de la finca) public double calcularPerimetro() (Se requiere un mĂŠtodo para calcular el Area) public double calcularArea() El primer mĂŠtodo que se va a construir es inicializarLado3. Este mĂŠtodo no tendrĂĄ retorno puesto que su objetivo es inicializar un atributo de la clase, de igual forma tampoco tendrĂĄ parĂĄmetros ya que para calcular el lado basta con aplicar la fĂłrmula para hallar la hipotenusa â&#x201E;&#x17D;2 =
đ?&#x2018;?12 + đ?&#x2018;?22
Se conocen c1 y c2, pues son respectivamente lado2 y lado1/2. De lo cual se concluye que se cuenta con toda la informaciĂłn necesaria, por lo cual no se requieren parĂĄmetros. Java provee la instrucciĂłn Math.pow para trabajar potenciaciĂłn y Math.sqrt para sacar raĂz cuadrada. Ejemplos de su uso son los siguientes: int num=4, exp=3; double dato1=Math.pow(num,exp); //num es la base y exp el exponente double dato=Math.sqrt(num);
Ahora proceda a construir el mĂŠtodo inicializarLado3. public void inicializarLado3(){ //Se usa la formula h=sqrt(cateto1 al cuadrado + cateto2 al cuadrado) lado3= } Los siguientes mĂŠtodos tampoco requieren de parĂĄmetros public double calcularPerimetro(){
} public double calcularArea(){ } Finalmente se construyen los mĂŠtodos set set para lado1 public void setLado1(double lado1){ this.lado1 = lado1; }
set para lado2 public void setLado2(double lado2){ this.lado2 = lado2; }
44
Luego de haber construido los métodos se procede a integrar todo en una clase. public class Finca { private double lado1, lado2, lado3; public void setLado1(
) {
} public void setLado2(
) {
}
public void inicializarLado3() {
} public double calcularPerimetro() {
} public double calcularArea() { }} Para ejecutar el programa es necesario que en la interfaz gráfica: - Se reserve memoria private Finca miFinca= new Finca(); - Se lea la información de los campos de texto y se declaren tantas variables como métodos con retorno se hayan hecho double double double double
lado1=Double.parseDouble(jTextFieldLado1.getText()); lado2=Double.parseDouble(jTextFieldLado1.getText()); perimetro=0; area=0;
- Se llame a los métodos set. Primero va la referencia al objeto seguida por el nombre del método y su correspondiente argumento. Adicionalmente se llama al método inicializarLado3, porque este método forma parte del requisito1
45
miFinca.setLado1(lado1); miFinca.setLado2(lado2); miFinca.inicializarLado3(); - Se llama a los demás métodos creados. perimetro= miFinca.calcularPerimetro(); jLabelSalida.setText("La cantidad de cable es "+perimetro); area= miFinca.calcularArea(); jLabelSalida.setText("El área de la finca es: "+area);
ACTIVIDAD Construya la clase para resolver la hoja de trabajo 2 e incluya las instrucciones necesarias para que el programa corra. Enunciado de la hoja de trabajo 2: Una constructora requiere una aplicación que le permita detectar la cantidad baldosas y de cajas requeridas para cubrir una superficie cuadrada. El constructor conoce los lados del piso y las dimensiones de cada baldosa. La baldosa no se vende se forma individual, solo por cajas y cada caja esa compuesta por 10 baldosas
public class Baldosa { private double largo, ancho; public void setLargo(double largo) { } public void setAncho(double ancho) { } public double calcularAreaB() { } public double getLargo() { } public double getAncho() { } }
46
public class Piso { public double ladoPiso; private Baldosa miBaldosa; public void setLadoPiso(double ladoPiso) { } public void setMiBaldosa(double largo, double ancho) { this.miBaldosa = new Baldosa(); } public double calcularAreaPiso(){ } public double calcularBaldosasRequeridas(){ } public double calcularCantidadCajas(){ } } Agregue las líneas necesarias para que el programa se ejecute. Tenga presente que aquí sólo debe reservarle memoria a la clase principal del mundo. Estas líneas deben ir en la interfaz gráfica.
47
1.8.7. Caso de estudio 3 Unidad I: El estudiante con notas Se desea crear una aplicación para manejar la información de un estudiante. Un estudiante tiene un código, un nombre, un sexo, dos asignaturas registradas (cada una de ellas con código y dos notas parciales) y una fecha de nacimiento. A su vez, una fecha está formada por un día, un mes y un año. Se debe permitir: Calcular la edad del estudiante Calcular la nota definitiva de cada asignatura si se hace a través de un promedio ponderado. Calcular la nota promedio del semestre, es decir, la nota que surge al promediar la nota definitiva de la asignatura 1 con la nota definitiva de la asignatura 2.
1.8.8.
Comprensión del problema
a) Requisitos funcionales NOMBRE R1 – Crear un nuevo estudiante RESUMEN Permite crear un nuevo estudiante ENTRADAS código, nombre, sexo, dia, mes, anio RESULTADOS Un nuevo estudiante ha sido creado
48
NOMBRE RESUMEN
R2 – Fijar una asignatura a un estudiante Permite fijar una asignatura a un estudiante para ello se ingresa el código y las dos notas
ENTRADAS código, nota1, nota2 RESULTADOS Se fijó la asignatura al estudiante
NOMBRE R3 – Calcular la nota definitiva para una asignatura RESUMEN Se calcula como el promedio ponderado de dos notas parciales ENTRADAS porcentaje1 y porcentaje2 RESULTADOS La nota definitiva
NOMBRE R4 – Calcular la nota definitiva del semestre RESUMEN Permite calcular el promedio aritmético de las definitivas de las dos asignaturas ENTRADAS Ninguna RESULTADOS La nota promedio NOMBRE RESUMEN
R5 – Calcular la edad del estudiante Permite calcular la edad del estudiante para ello se resta la fecha actual de la fecha de nacimiento
ENTRADAS Ninguna RESULTADOS La edad
b) El modelo del mundo del problema
1. Identificar las entidades o clases Las clases identificadas son las siguientes: ENTIDAD DEL MUNDO Estudiante Fecha Asignatura
DESCRIPCIÓN Es la entidad más importante del mundo del problema. Atributo del estudiante Atributo del estudiante
Para identificar los métodos se deben resaltar los verbos Se desea crear una aplicación para manejar la información de un estudiante. Un estudiante tiene un código, un nombre, un sexo, dos asignaturas registradas (cada una de ellas con código y dos
49
notas parciales) y una fecha de nacimiento. A su vez, una fecha está formada por un día, un mes y un año. Se debe permitir: Calcular la edad del estudiante Calcular la nota definitiva de cada asignatura si se hace a través de un promedio ponderado. Calcular la nota promedio del semestre, es decir, la nota que surge al promediar la nota definitiva de la asignatura 1 con la nota definitiva de la asignatura 2.
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA FECHA ATRIBUTO dia mes anio
VALORES POSIBLES enteros positivos mayores que 1 y menores de 32 enteros mayores que 1 y menores que 13 enteros positivos IDENTIFICACIÓN DE MÉTODOS
Tipo de dato int int int
(para crear una fecha se debe fijar cada uno de los atributos) public void setDia(int dia) public void setMes(int mes) public void setAnio(int anio) (se debe poder obtener la fecha actual) public void inicializarFechaActual( ) (Permite restar a la fecha actual la fecha de nacimiento) public int calcularDiferenciaConFechaActual( Fecha miFecha )
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA ASIGNATURA ATRIBUTO código nota1 nota2 definitiva
VALORES POSIBLES Cadena de caracteres Un número real mayor que 0 y menor o igual a 5 Un número real mayor que 0 y menor o igual a 5 Un número real mayor que 0 y menor o igual a 5 IDENTIFICACIÓN DE MÉTODOS
Tipo de dato String double double double
(para crear una Asignatura se debe fijar cada uno de los atributos que el usuario conoce) public void setCodigo(String codigo) public void setNota1(double nota1) public void setNota2(double nota2) (para calcular la nota definitiva se requiere un método que calcule el promedio ponderado) public double calcularDef(double porcentaje1, double porcentaje2) (se debe poder devolver la definitiva) public double getDefinitiva()
50
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA ESTUDIANTE ATRIBUTO codigo nombre miFechaNacimiento miAsignatura1 miAsignatura2
VALORES POSIBLES Cadena de caracteres Cadena de caracteres Referencia a objeto de tipo Fecha Referencia a objeto de tipo Asignatura Referencia a objeto de tipo Asignatura IDENTIFICACIÓN DE MÉTODOS
Tipo de dato String String Fecha Asignatura Asignatura
(para crear un estudiante se debe fijar cada uno de los atributos) public void setCodigo(String codigo) public void setNombre(String nombre) public void setSexo(boolean sexo) public void setMiFechaNacimiento(int dia, int mes, int anio) public void setMiAsignatura1(String codigo, double nota1, double nota2) public void setMiAsignatura2(String codigo, double nota1, double nota2)
(Se debe poder calcular la definitiva para cada asignatura) public double calcularDefinitivaA1(double porcentaje1, double porcentaje2) public double calcularDefinitivaA2(double porcentaje1, double porcentaje2) (para calcular la nota definitiva se requiere un método que haga el promedio de las dos notas) public double calcularNotaPromedio() (para calcular la edad se requiere de un método que tome la fecha actual y la reste de la fecha de nacimiento) public int calcularEdad() El diagrama de clases correspondiente para este caso de estudio es el siguiente:
51
La primera clase que se va a trabajar es la clase Fecha. Se iniciará con la construcción del método inicializarFechaActual, en el cual se crea una referencia a un objeto de tipo GregorianCalendar para luego inicializarlo con la fecha actual. Los siguientes métodos están basados en la clase Fecha del caso del estudio del Empleado del Proyecto CUPI2 . public void inicializarFechaActual( ) { GregorianCalendar diaHoy = new GregorianCalendar( ); anio = diaHoy.get( Calendar.YEAR ); mes = diaHoy.get( Calendar.MONTH ) + 1; dia = diaHoy.get( Calendar.DAY_OF_MONTH ); } El método calcularDiferenciaConFechaActual permite calcular la diferencia entre la fecha actual y una fecha ingresada por el usuario public int calcularDiferenciaConFechaActual( Fecha miFecha ) { int diferenciaEnMeses = 0; diferenciaEnMeses = ( miFecha.getMes() - mes )+12 * ( miFecha.getAnio() - anio ) ; //En caso de que el día no sea mayor se debe restar un mes. Es decir, no //se tiene la cantidad de días suficientes para poder sumar un mes más. if(dia >= miFecha.getDia()
) 52
diferenciaEnMeses --; return diferenciaEnMeses ; } Continuando con la clase Asignatura, se tienen los siguientes métodos: El método calcularDef() lleva dos parámetros porcentaje1 y porcentaje2. Recuerde que los parámetros son los datos necesarios para resolver el problema y que no pertenecen al objeto. Estos porcentajes no pertenecen al objeto mientras que código, nota1, nota2 y definitiva si pertenecen. Antes de continuar con la contrucción del método se requiere aclarar el concepto de promedio ponderado. Este es un promedio en el cual el resultado surge al asignarle a cada valor un peso, logrando con ello que unos valores tengan mas relevancia que otros. Por ejemplo si se hablara de las siguientes notas definitivas de asignaturas: Matemática: 4 Programación: 5 El promedio aritmético daría 4.5, pero si se pondera cada asignatura asignando a matemática el 40% y a Programación el 60%, el promedio ponderado obtenido sería: 4 x 4/100 + 5 x 6/100 =4 x 0,4 + 5 x 0,6 = 4,6 Ahora bien, habiendo hecho esta aclaración el método calcularDef quedaría de la siguiente forma: public double calcularDef(double porcentaje1, double porcentaje2) { definitiva= nota1*porcentaje1/100+nota2*porcentaje2/100; return definitiva; }
El método getDefinitiva() devuelve un double con la nota definitiva: public double getDefinitiva() { return definitiva; }
Finalmente de la clase Estudiante se tienen los siguientes métodos: El método setMiFechaNacimiento tiene 3 parámetros (dia, mes, anio) que permiten inicializar la fecha de nacimiento. Para ello es necesario reservarle memoria a miFechaNacimiento y llamar a los métodos set. public void setMiFechaNacimiento(int dia, int mes, int anio) { this.miFechaNacimiento = new Fecha(); miFechaNacimiento.setDia(dia); miFechaNacimiento.setMes(mes); miFechaNacimiento.setAnio(anio);} 53
Los métodos setMiAsignatura permiten inicializar cada una de las asignaturas. Para inicializar una asignatura el usuario debe ingresar el código y las dos notas. La inicialización incluye reservar memoria y la llamada a cada uno de los métodos set. public void setMiAsignatura1(String codigo, double nota1, double nota2) { this.miAsignatura1 = new Asignatura(); miAsignatura1.setCodigo(codigo); miAsignatura1.setNota1(nota1); miAsignatura1.setNota2(nota2); } public void setMiAsignatura2(String codigo, double nota1, double nota2) { this.miAsignatura2 = new Asignatura(); miAsignatura2.setCodigo(codigo); miAsignatura2.setNota1(nota1); miAsignatura2.setNota2(nota2); } El método calcularEdad() no tiene parámetros debido a que previamente se ingresó la fecha de nacimiento del estudiante y con esta información es suficiente para obtener la edad. public int calcularEdad() { Fecha actual=new Fecha(); actual.inicializarFechaActual(); return miFechaNacimiento.calcularDiferenciaConFechaActual(actual)/12; } Los métodos calcularDefinitiva permiten calcular la definitiva de cada asignatura, para ello se ha agregado dos parámetros, porcentaje1 y porcentaje2. public double calcularDefinitivaA1(double porcentaje1, double porcentaje2) { return miAsignatura1.calcularDef(porcentaje1, porcentaje2); } public double calcularDefinitivaA2(double porcentaje1, double porcentaje2) { return miAsignatura2.calcularDef(porcentaje1, porcentaje2); } El método calcularNotaPromedio() no requiere parámetros puesto que con la información con la que cuenta el objeto es suficiente. Para que este método funcione correctamente se debe haber invocado previamente a los métodos calcularDefinitivaA1 y calcularDefinitivaA2. public double calcularNotaPromedio() { return miAsignatura1.getDefinitiva()+miAsignatura2.getDefinitiva(); }
54
Para ejecutar el programa es necesario en la interfaz gráfica: - Reservar memoria private Estudiante miEstudiante=new Estudiante(); - Leer la información de los campos de texto String codigo=jTextFieldCodigo.getText(); String nombre=jTextFieldNombre.getText(); boolean sexo=true; int dia=Integer.parseInt(jTextFieldDia.getText()); int mes=Integer.parseInt(jTextFieldMes.getText()); int anio=Integer.parseInt(jTextFieldAnio.getText()); String codigoA1=jTextFieldCodigoA1.getText(); double nota1A1=Double.parseDouble(jTextFieldNota1A1.getText()); double nota2A1=Double.parseDouble(jTextFieldNota2A1.getText()); String codigoA2=jTextFieldCodigoA2.getText(); double nota1A2=Double.parseDouble(jTextFieldNota1A2.getText()); double nota2A2=Double.parseDouble(jTextFieldNota2A2.getText()); double p1A1=Double.parseDouble(jTextFieldPorcentaje1N1.getText()); double p2A1=Double.parseDouble(jTextFieldPorcentaje2A1.getText()); double p1A2=Double.parseDouble(jTextFieldPorcentaje1A2.getText()); double p2A2=Double.parseDouble(jTextFieldPorcentaje2A2.getText()); if(jRadioButtonMasculino.isSelected()==true) sexo=false; - Llamar a los métodos set. Primero va la referencia al objeto seguida por el nombre del método y su correspondiente argumento. miEstudiante.setCodigo(codigo); miEstudiante.setSexo(sexo); miEstudiante.setMiAsignatura1(codigoA1, nota1A1, nota2A1); miEstudiante.setMiAsignatura2(codigoA2, nota1A2, nota2A2); miEstudiante.setMiFechaNacimiento(dia, mes, anio); Luego se debe calcular la nota definitiva para ambas asignaturas. Esto debe realizarse antes de calcular la nota promedio. miEstudiante.calcularDefinitivaA1(p1A1, p2A1); miEstudiante.calcularDefinitivaA1(p1A2, p2A2); jLabelSalida.setText("El promedio es"+miEstudiante.calcularNotaPromedio() ); Finalmente se calcula la edad jLabelSalida.setText("La edad es "+miEstudiante.calcularEdad());
55
1.8.9. Caso de estudio 4 Unidad I: El minimercado Se desea crear una una Aplicación para registrar compras en un minimercado, el cual ofrece tres diferentes productos. Se sabe que cada producto tiene un código, una descripción y un precio unitario. Se debe permitir: Agregar un producto a la compra. Aumentar en 1 la cantidad de existencias adquiridas de un producto incluido en la compra Indicar la totalidad de artículos incluidos en la compra Calcular el total a pagar por cada tipo de producto Calcular el total a pagar por el total de la compra Reiniciar la compra
1.8.10. Comprensión del problema a) Requisitos funcionales NOMBRE R1 – Agregar un producto a la compra RESUMEN Permite agregar un producto a la compra ENTRADAS codigo, descripcion, precioUnitario RESULTADOS Un producto se ha incluido en la compra
56
NOMBRE
R2- Aumentar en uno la cantidad de existencias adquiridas de un producto en la compra Incrementa en uno la cantidad de existencias
RESUMEN ENTRADAS El tipo del producto del cual se va a adquirir una unidad más RESULTADOS La compra tiene una existencia mas del tipo de producto indicado
NOMBRE R3 – Indicar la totalidad de artículos incluidos en la compra RESUMEN Se suman todos los artículos que hay en la compra ENTRADAS Ninguna RESULTADOS La cantidad de artículos que tienen la compra
NOMBRE RESUMEN ENTRADAS
R4 – Calcular el total a pagar por cada tipo de producto Permite obtener el valor total a pagar por cada tipo de producto
RESULTADOS Total a pagar por el primer producto Total a pagar por el segundo producto Total a pagar por el tercer producto NOMBRE R5 – Calcular el total a pagar por el total de la compra RESUMEN Permite calcular el valor que se debe pagar por la compra ENTRADAS Ninguna RESULTADOS Total a pagar por la compra
NOMBRE R6 – Reiniciar la compra RESUMEN Se crea una nueva compra ENTRADAS Ninguna RESULTADOS Se inicia una nueva compra
b) El modelo del mundo del problema
- Identificar las entidades o clases Las clases identificadas son las siguientes:
57
ENTIDAD DEL MUNDO Compra Producto
DESCRIPCIÓN Es la entidad más importante del mundo del problema. Es un atributo de la compra
- Identificar los métodos. Para ellos se deben resaltar los verbos
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA PRODUCTO ATRIBUTO codigo descripcion precioUnitario cantidadE
VALORES POSIBLES Cadena de caracteres Cadena de caracteres Valor real entero
Tipo de dato String String double int
IDENTIFICACIÓN DE MÉTODOS (para crear un Producto se hará uso de un método constructor) public Producto(String codigo, String descripcion, double precioUnitario) (se debe poder agregar una unidad a la cantidad de existencia del producto) public int agregarExistencia() (Se debe poder calcular el precio de la totalidad de existencias adquiridas de ese producto) public double calcularPrecioPedidoDelProducto()
(Se requiere devolver la cantidad de existencias del producto) public int getCantidadE()
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA COMPRA ATRIBUTO
VALORES POSIBLES
Tipo de dato
IDENTIFICACIÓN DE MÉTODOS (Se debe permitir agregar los productos a la compra) public void setMiProducto1(String codigo, String descripcion, double precioUnitario) public void setMiProducto2(String codigo, String descripcion, double precioUnitario) public void setMiProducto3(String codigo, String descripcion, precioUnitario) (Aumentar en uno la cantidad de existencias adquiridas de un producto en la compra) public void agregar UnidadProducto1()
58
double
public void agregar UnidadProducto2() public void agregar UnidadProducto3() (Se requiere calcular el precio de la factura) public double calcularPrecioFactura() (Se debe devolver la cantidad de artĂculos que se incluyeron en la compra) public int getContadorAdquisiciones() (Se necesitan mĂŠtodos para devolver los productos) public Producto getMiProducto1() public Producto getMiProducto2() public Producto getMiProducto3()
El diagrama de clases correspondiente para este caso de estudio es el siguiente:
59
La construcción de esta aplicación se debe iniciar por la clase Producto. Como se mencionó con anterioridad en la clase Producto se trabajó un método constructor. Un constructor permite inicializar las variables de la clase. Es sintácticamente similar a un método y se caracteriza por tener el mismo nombre de la clase y no llevar ningún tipo de retorno, ni siquiera void. Tenga en cuenta que una clase cualquiera puede tener declarados atributos los cuales pueden ser variables de entrada o salida. Para la clase Producto los atributos identificados fueron: codigo descripcion precioUnitario cantidadE
Los valores de los tres primeros atributos los conoce el cajero y por ello se pueden considerar como variables de entrada, es decir él sabe el código del producto que va a vender, la descripción y el precio unitario. No obstante, para él es imposible conocer cuántas existencias de ese producto particular va a incluir el cliente en su compra, en tal caso se dirá que es una variable de salida, pues debe calcularse. Partiendo de lo anterior, el constructor de la clase Producto tiene 3 parámetros puesto que se necesita inicializar 3 atributos de la clase, a saber: código, descripción y precioUnitario. public Producto(String codigo, String descripcion, double precioUnitario) { this.codigo = codigo; this.descripcion = descripcion; this.precioUnitario=precioUnitario; }
La cantidad de existencias se calcula a través del método agregarExistencia(). public int agregarExistencia() { cantidadE++; return cantidadE; }
Dicho método requiere de un contador, pues cada vez que se agregue una existencia del producto se debe incrementar la variable contadorE en 1. Un contador es una variable que incrementa o decrementa su valor en una cantidad fija. Se suele utilizar cuando se presentan requisitos tales como: Obtener la cantidad de … Indicar el total de … Contar la cantidad de … La sintaxis de su uso es la siguiente: contador=contador+1; // cuando se incrementa de 1 en 1, forma larga contador+ +; //cuando se incrementa de 1 en 1, forma abreviada contador= contador+2; // cuando se incrementa de 2 en 2, forma larga contador+=2; // cuando se incrementa de 2 en 2, forma abreviada 60
contador--; //cuando se decrementa de 1 en 1, forma abreviada Tenga
en
cuenta
que
la
variable
contador
debe
declararse
de
tipo
int.
- El método calcularPrecioPedidoDelProducto no requiere parámetros, puesto que se conoce la cantidad de existencias del producto que el cliente incluyó en su compra y además el precio unitario. public double calcularPrecioPedidoDelProducto() {return cantidadE*precioUnitario;}
De la clase Compra se tienen los siguientes métodos: - El método setMiProducto1 tiene 3 parámetros, es decir, los tres datos que se requieren para poderle reservar memoria al producto1 public void setMiProducto1(String codigo, String descripcion, double precioUnitario) { miProducto1=new Producto(codigo, descripcion, precioUnitario); }
- El método agregarUnidadProducto1() permite incrementar en uno del contador de existencias de dicho producto. No tiene parámetros puesto que no requiere información externa a la que posee el objeto. public void agregarUnidadProducto1() { miProducto1.agregarExistencia(); contadorAdquisiciones++; }
- El método calcularPrecioFactura() permite calcular el precio total de la factura. Esto se hace sumando el precio total de las existencias del producto uno, con el precio total de las existencias del producto dos y el precio total de las existencias del producto tres. public double calcularPrecioFactura() { return miProducto1.calcularPrecioPedidoDelProducto()*miProducto2.calcularPrecioP edidoDelProducto()+miProducto3.calcularPrecioPedidoDelProducto(); }
- El método getMiProducto1() devuelve toda la información de miProducto1, observe que el retorno es de tipo Producto. public Producto getMiProducto1() { return miProducto1; }
61
- El mĂŠtodo getContadorAdquisiciones()devuelve el valor del contador de adquisiciones. public int getContadorAdquisiciones() { return contadorAdquisiciones; }
62
2.
EXPRESIONES Y ESTRUCTURAS DE DECISION
Objetivos Pedagógicos Al finalizar la unidad el estudiante estará en capacidad de: Utilizar instrucciones condicionales simples y anidadas para dar solución a problemas que requieren la toma de decisiones. Utilizar constantes al momento de modelar las características de un objeto Utilizar expresiones dentro de métodos como un medio para modificar el estado de un objeto. 2.1. Introducción En esta unidad se trabajarán casos de estudio que requieren para su solución la toma de decisiones, es decir, necesitan la incorporación de estructuras de selección. Para poder iniciar con esta tématica es importante que previamente se manejen los conceptos de expresiones y operadores entre Strings. a) Expresiones Aunque en la unidad anterior se hizo una breve explicación sobre el concepto de expresiones. En esta unidad se ampliará este concepto. Una expresión está formada por variables, constantes y/o operadores. Cuando va a crear una expresión se deben seguir unas reglas básicas de codificación. Tales reglas son: 1. Si se tiene un cociente y alguno de sus términos involucra una operación, éste debe encerrarse entre paréntesis. Ejemplo
H
p p / (b c) bc
2. Si se tiene una potencia debe usarse la instrucción Math.pow. El primer término es la base y el segundo es el exponente. El resultado de la potencia es un double.
(a t ) n1 Math. pow( a t , n 1 ) 3. Cuando se tenga una raíz ésta puede expresarse en forma de potencia. Puede utilizarse la instrucción Math.sqrt para sacar raíz cuadrada. n
x Math. pow( x, 1.0 / n ) x Math.sqrt( x )
4. Se debe tener clara la precedencia de los operadores. Este orden es fundamental para determinar el resultado de una expresión. A continuación se muestra una tabla en la cual se listan los operadores en orden de precedencia de mayor a menor.
63
Tipo de operadores
Operadores de este tipo
Ejemplo
Operadores posfijos
expr++, expr--
int a=b++;
Operadores unarios
++expr, --expr, +expr, -expr, !
int a=--b; boolean centinela=false; centinela=!centinela;
Creación o conversión
new
Casa miCasa=new Casa();
Multiplicación
*, /, %
int res=a*(b%2);
Suma
+, -
int res=a-5;
Relacionales o comparación
<, >, <=, >=
Igualdad
==, !=
a==b, a!=b
AND lógico
&&
centinela==false&&estado==true
OR lógico
||
centinela==false||estado==true
Condicional
?:
Asignación
=, +=, -=, *=, /=, %= Precedencia de operadores
if(a>=b)
a*=5; //a=a*5;
ACTIVIDAD 1. Identifique los valores finales de las variables enteras proporcionadas a continuación: a) int a = b = c = a = b = c = b = c =
a, b, c; 5 7 9 a + 13+c b/a + 3 + 5 – a * 7 a + (b – c) --a c + 5 – b*4 – a/3
b) int a = b = c = d = d = c = a = b =
a, b, c, d; 7 a (int)(Math.pow(a,b+1)) 0 a*b + (c – d)/5 c - d 45 - a + (-b) c – a
c) int a = b = c = d = a = b = c =
a, b, c, d; 66; 45; b % a; c / 21 * a / (b % 5); a % 3 - 5 % 2; b + a / 3 % 2 * ((64 / 3 % 2) + (3 % 2) + 12) 5*b + c % 2; 64
d = a -(b % c) / 3; d) int x,y,z,w; x = 3; y = 5; z = 11; w = 3; x -= (z + y -= (--w z *= (--x w /= (x %
(--w + y++) * 8); - ++z) % w; + --y); y);
2. Determine el valor final de cada una de las siguientes variables booleanas: a) boolean t, u, v, w, x, y, z; t = !(!true); u = false; v = u || true; z= false; w = v || u; x = (v || w) & !(!t || !u); y = (!x && !v) && (!t); z = !(!w); b) boolean t, u, v, w, x, y, z; t = (!true && false); u = !((!true) && (!false || true)); v = (false || t) && (true || u); w = (v || u) x = (t && !t && !u) && false); y = (!x && !v) ; z = !(x && !false) && false;
4. Dadas las siguientes fórmulas debe codificarlas en su correspondiente estructura de programación.
h
b k d 5 x3 8 * b hd 5 e 2*a 3/ h l u
t p
65
r t y
mv u x *5
b) Operaciones sobre Strings A continuación se proporcionan algunas de las operaciones que pueden realizarse sobre Strings a. Concatenación: Para unir dos Strings Java proporciona el operador +. Ejemplo: String nombre = "Max", apellido="Steel"; String completo = nombre + " " + apellido;
De igual forma proporciona la instrucción concat. El ejemplo anterior con la instrucción concat podría resolverse como: completo=((nombre.concat(" ")).concat(apellido)); b. Extracción de caracteres 1. charAt(): permite extraer un solo carácter de la cadena. Ejemplo: String nombre = "Max Steel", char inicial=nombre.charAt(0); //inicial queda valiendo M char segunda=nombre.charAt(1); //segunda queda valiendo a c. Modificación de un String Los métodos que proporciona Java para modificar un String son los siguientes: String replace( char original, char reemplazo ); String toLowerCase(); String toUpperCase(); String trim(); El método replace permite reemplazar un carácter dentro de un String. Los métodos toLowerCase() y toUpperCase() permiten convertir los caracteres de un String a minúscula o mayúscula respectivamente. El método trim() permite eliminar los espacios al comienzo o al final presentes en un String. Ejemplo: String nombre = "Max Steel"; nombre=nombre.replace('a', 'o'); String codigo=" 12 "; int numero=Integer.parseInt(codigo.trim());
d. Comparación de cadenas Java proporciona las siguientes instrucciones para comparar cadenas:
66
boolean equals ( Object cadena ); boolean equalsIgnoreCase ( Object cadena ); int compareTo( String cadena );
El método equals compara Strings teniendo en cuenta si están en mayúsculas o minúsculas. El método equalsIgnoreCase, ignora éste aspecto. Algunos ejemplos de uso son: String nombre = "Max", apellido="Steel"; boolean res=nombre.equals(apellido); //Esto da falso boolean res1=nombre.equalsIgnoreCase(nombre.toUpperCase()); //Esto da true
Es importante que tenga claro que la instrucción equals y el == no realizan la misma tarea. Equals compara los caracteres de ambas cadenas, mientras que el == compara las referencias de ambos objetos para comprobar si se trata de una misma instancia. El método compareTo() aplicado a dos Strings permite determinar cuál de ellas es menor o mayor alfabéticamente o si son iguales. Ejemplo: String nombre = "Max", apellido="Steel"; int resultado= nombre.compareTo(apellido); //a resultado se le asigna un //número negativo puesto que la M es alfabéticamente menor que la S. Si el método retorna un valor menor que cero entonces el primer String es menor alfabéticamente que la cadena con la que se compara. Si el valor es positivo entonces ocurre lo contrario. Si es igual a cero es porque ambos Strings son iguales. Algunos ejemplos que permitan aclarar el término alfabéticamente menor y alfabéticamente menor son: palabra1
palabra2
“vaca” “leche” “tabla” “camino” “azucar” “maleta” “asignatura” “amigo”
“caballo” “miel” “cuadro” “via” “chocolate” “maleta” “asignar” “amistad”
Resultado palabra1.compareTo(palabra2) >0 >0 >0 <0 <0 ==0 >0 <0
de
Es de anotar que el método compareTo realiza la ordenación basándose en los códigos ASCII, por lo tanto cuando se usa para ordenar String su salida no será correcta en los siguientes casos: Si hay acentos Está presente la letra ñ Hay números, puesto que los ordenaría mal Ejemplo: 1,10,110,2,3,4,45,5,.... Hay mayúsculas y minúsculas mezcladas. Las mayúsculas saldrán antes que todas las entradas con minúsculas. Si desea un método que permita ordenar Strings y que no presente los anteriores inconvenientes puede consultar Collator.
67
e. Búsqueda en las cadenas Para determinar si un carácter está presente en una cadena se puede hacer uso de dos métodos: int indexOf ( int caracter ); int lastIndexOf ( int caracter ); El método indexOf() devuelve la posición de la primera ocurrencia de un carácter dentro del String. El método lastIndexOf() devuelve la posición de la última aparición del carácter. Ejemplos de uso de estas instrucciones son: int pos=nombre.indexOf('a'); f. Cálculo de la longitud Para calcular la longitud de una cadena se utiliza el método length(). Por ejemplo si se tiene: String nombre = “Max”; int longi=cadena.length(); // Debe retornar 5
2.2. Caso de estudio 1 Unidad II: Juguetería Se desea crear una Aplicación para manejar la información de una Tienda. En la tienda se venden juguetes, cada Juguete tiene un código, un nombre, un tipo (O->Femenino 1->Masculino 2-> Unisex) y un precio. Se debe permitir agregar un nuevo juguete Informar cuantos juguetes hay por cada tipo Informar la cantidad total de juguetes Informar el valor total de todos los juguetes que hay en la tienda Informar el valor promedio de los juguetes por tipo Informar el tipo del cual hay más juguetes Ordenar de menor a mayor la cantidad de existencias de juguetes por tipo. Ejemplo si hay 5 juguetes femeninos, 2 masculinos y 7 unisex, el ordenamiento quedaría como 2 masculino, 5 femenino y 7 unisex. Comenzar una nueva tienda de juguetes 2.2.1.
Comprensión del problema
Tal como se planteó en el capítulo previo, lo primero que debe hacerse para dar solución a un problema es entender dicho problema, para ello es importante identificar los requisitos funcionales y los no funcionales, además del modelo del mundo del problema. a) Requisitos funcionales NOMBRE R1 – Informar la cantidad de juguetes que hay por tipo RESUMEN Permite contar la cantidad de juguetes que hay de un determinado tipo ENTRADAS El tipo RESULTADOS La cantidad de juguetes por tipo 68
NOMBRE R2 – Informar la cantidad total de juguetes RESUMEN Permite calcular el total de juguetes que hay en la tienda ENTRADAS Ninguna RESULTADOS La cantidad total del juguetes
NOMBRE R3 – Informar el valor total de todos juguetes RESUMEN Se suma el valor total de los juguetes ENTRADAS Ninguna RESULTADOS El valor total de los juguetes
NOMBRE RESUMEN
R4 – Informar el valor promedio de los juguetes por tipo Se acumula el valor total de los juguetes del tipo solicitado y se divide por la cantidad de juguetes de ese tipo.
ENTRADAS El tipo RESULTADOS El valor promedio
NOMBRE RESUMEN
R5 – Informar el tipo del cual hay más juguetes Se debe realizar una comparación entre los 3 tipos para determinar cuál es el que tiene mayor cantidad de juguetes. Los posibles salidas son O->Femenino, 1->Masculino y 2-> Unisex.
ENTRADAS Ninguna RESULTADOS El tipo del cual hay más juguetes
NOMBRE R6 – Comenzar una nueva tienda de juguetes RESUMEN Una nueva tienda de juguetes es creada y no tiene juguetes en su interior ENTRADAS Ninguna RESULTADOS Se comienza una nueva tienda
69
NOMBRE RESUMEN
R7 – Ordenar la cantidad de existencias de juguetes por tipo Se debe ordenar de menor a mayor la cantidad de existencias de juguetes por tipo. Ejemplo, si hay 5 juguetes femeninos, 2 masculinos y 7 unisex, el ordenamiento quedaría como 2 masculino, 5 femenino y 7 unisex.
ENTRADAS Ninguna RESULTADOS La ordenación de acuerdo a la cantidad de existencias por tipo
2.2.2.Especificación de la Interfaz de usuario Una parte importante del diseño de la solución es la especificación de la interfaz de usuario. La siguiente figura muestra el diseño seleccionado para este caso de estudio:
La ventana de la aplicación está dividida en 2 zonas: La primera de ellas permite ingresar la información de cada juguete. Allí se solicita el código, el nombre, el tipo y el precio del juguete. En la segunda zona hay 7 botones, cada uno de ellos asociado a un requisito funcional. Inicialmente se observan dos botones. Desde el primer botón es posible obtener la cantidad de juguetes por tipo y desde el segundo, calcular el valor promedio por tipo. Para ambos casos se proporciona un menú desplegable que permite seleccionar el tipo deseado. A continuación se proporcionan 4 botones, entre ellos se encuentran los que permiten calcular el total de juguetes y crear una nueva tienda.
2.2.3.Otros elementos de modelado
En el nivel anterior se introdujo el concepto de tipos de datos simples de datos (byte, short, int, long, float, double, char y boolean) y el tipo String. También se explicaron los diferentes tipos de operadores. Ahora se introducirá el concepto de constantes, a través de las cuales es posible definir datos que no cambiarán a lo largo de la ejecución de un programa.
70
La declaración de una constante incluye la palabra final. Se debe tener en cuenta que los nombres de las constantes se escriben en mayúscula y si están formados por más de una palabra se separan con guión bajo. Una constante puede usarse para definir el dominio de un atributo o para representar valores inmutables. A continuación se muestran algunos ejemplos del uso de constantes. Las siguientes constantes representan valores inmutables
public final static double CONSTANTE_PI = 3.1416; public final static double IVA = 0.16;
Las siguientes constantes representan el dominio de un atributo public final static int FEMENINO = 1; public final static int MASCULINO = 2; El concepto de constantes aplicado al caso de estudio de la Juguetería: public class Juguete {
En la columna de la izquierda se puede observar:
//Constantes public final static int FEMENINO=0; public final static int MASCULINO=1; public final static int UNISEX=2; //Atributos private String codigo, private int tipo; private double precio; }
-Se declara FEMENINO, para representar el primer valor posible del atributo tipo de juguete. Se le asigna un valor de cero. -Se declara MASCULINO, para representar el segundo valor posible del atributo tipo de juguete. Se le asigna un valor de 1.
nombre;
-Se declara UNISEX, para representar el tercer valor posible del atributo tipo de juguete. Se le asigna un valor de 2. -Se declara el atributo “tipo”
b) El modelo del mundo del problema Las actividades que se deben realizar para construir el modelo del mundo son las siguientes: Identificar las entidades o clases. Las clases identificadas son las siguientes:
ENTIDAD DEL MUNDO Tienda Juguete
DESCRIPCIÓN Es la entidad más importante del mundo del problema. Es un atributo de la tienda
71
Identificar los métodos Los atributos y métodos identificados para cada una de las clases se muestran en las siguientes tablas.
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA JUGUETE ATRIBUTO codigo nombre tipo precio
VALORES POSIBLES Cadena de caracteres Cadena de caracteres Valor entero positivo Valor real positivo
Tipo de dato String String int double
IDENTIFICACIÓN DE MÉTODOS (para crear un juguete se debe fijar cada uno de los atributos) public void setPrecio(double precio) public void setCodigo(String codigo) public void setNombre(String nombre) public void setTipo(int tipo) (obtener el precio y el tipo del juguete) public double getPrecio() public int getTipo()
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA TIENDA ATRIBUTO miJuguete contadorF contadorM contadorU acumuladorPrecioF acumuladorPrecioM acumuladorPrecioU
VALORES POSIBLES Referencia a un objeto de tipo Juguete Valor entero positivo Valor entero positivo Valor entero positivo Valor real positivo Valor real positivo Valor real positivo
Tipo de dato Juguete int int int double double double
IDENTIFICACIÓN DE MÉTODOS (para crear una tienda e inicializar variables se debe construir un constructor) public Tienda() (Para agregar un juguete a la tienda se cuenta con el siguiente método) public void agregarJuguete(String codigo, String nombre, int tipo, double precio) (Se requiere de un método que permita determinar la cantidad de juguetes por tipo) public void contarPorTipo(int tipo) (Se necesita un método que calcule el total de juguetes) public int devolverTotalJuguetes() (Se requiere de un método para calcular el precio total de los juguetes) public double calcularPrecioTotal()
72
(Se requiere un método para determinar cuál tipo tiene más juguetes) public String determinarTipoMayor() (Se necesita un método para poder ordenar por tipo) public String ordenar() (Se necesita un método para poder reiniciar la tienda) public void comenzarTienda()
Las Relaciones entre las clases del mundo
73
La construcción de esta aplicación inicia con la clase Juguete, que sería la siguiente: public class Juguete { //Constantes public final static int FEMENINO=0; public final static int MASCULINO=1; public final static int UNISEX=2; //Atributos private String codigo, private int tipo; private double precio;
nombre;
/** * Devuelve el precio * @return precio */ public double getPrecio() { return precio; } /** * Permite fijar el precio * @param precio El precio del juguete, precio>0 */ public void setPrecio(double precio) { this.precio = precio; } /** * Permite fijar el código * @param codigo El codigo del producto, codigo!=null */ public void setCodigo(String codigo) { this.codigo = codigo; } /** * Permite fijar el nombre del juguete * @param nombre El nombre del juguete, nombre!=null */ public void setNombre(String nombre) { this.nombre = nombre; } /** * Devuelve el tipo del juguete * @return tipo */ public int getTipo() { return tipo; } /** * Permite fijar el tipo del juguete * @param tipo El tipo del juguete, tipo>=0 && tipo<3 */ public void setTipo(int tipo) { this.tipo = tipo; }}
Para poder iniciar con la construcción de los métodos de la clase Tienda es necesario incorporar el concepto de instrucciones condicionales o estructuras de decisión. 74
2.2.4.Instrucciones Condicionales Este tipo de instrucciones permite ejecutar una instrucción sólo si se cumple una determinada condición. La estructura condicional más usada es el if. La forma de representación de la sentencia if es: if (condición) { // Instrucción o conjunto de instrucciones } La condición del if se expresa mediante una expresión booleana que se evalúa para ver si la condición es verdadera o falsa. Ejemplo: if(tipo==Juguete.FEMENINO) {return contadorF;} Recuerde que previamente se declaró la constante public final static int FEMENINO=0; Si el resultado de la evaluación de la condición es true, entonces se ejecutan todas las instrucciones que están dentro de las llaves {}, es decir, dentro del bloque. De lo contrario, las instrucciones dentro del bloque no se ejecutan. Es de resaltar, que luego de ejecutar el bloque de instrucciones relacionas con el if, la ejecución del programa continúa con el conjunto de instrucciones que se encuentran por debajo del bloque. Si lo que se requiere es escribir una instrucción alternativa doble se utiliza el if-else: if (condicion) { // instrucción o conjunto de instrucciones 1 } else { // instrucción o conjunto de instrucciones 2 } Si luego de evaluar la condición del if el resultado es true, se ejecutará el bloque de instrucciones asociados al if. De lo contrario, se ejecuta el conjunto de instrucciones asociados al else. En el caso de requerir estructuras condicionales más complejas se pueden anidar sentencias if Si inmediatamente después de la condición del if no hay llaves se asume que éste tiene una sola instrucción. Lo recomendable es que siempre se le coloquen llaves para seguir con los lineamientos de las buenas prácticas de programación. Ejemplo, si se tiene el siguiente código:
if(miJuguete.getTipo()==Juguete.FEMENINO) contadorF++; else 75
if(miJuguete.getTipo()==Juguete.MASCULINO) contadorM++; else contadorU++;
es equivalente a: if(miJuguete.getTipo()==Juguete.FEMENINO) {contadorF++; } else if(miJuguete.getTipo()==Juguete.MASCULINO) {contadorM++; } else {contadorU++; }
No hay límite con respecto al número de estructuras de selección doble que pueden ponerse en cascada. Cuando el if es anidado o en cascada las condiciones se examinan en orden descendente pasando de una a otra si la anterior resulta falsa. Cuando se encuentre la condición verdadera, entonces se efectúa la acción correspondiente a dicha condición y no se continúa examinando el resto de la estructura. En caso de no encontrar una condición verdadera se ejecuta la acción correspondiente al último else. Ahora bien, retomando el caso de estudio sobre la Tienda: “Se desea crear una Aplicación para manejar la información de una Tienda. En la tienda se venden juguetes, cada Juguete tiene un código, un nombre, un tipo (O->Femenino 1->Masculino 2-> Unisex) y un precio. Se debe permitir agregar un nuevo juguete Informar cuantos juguetes hay por cada tipo Informar la cantidad total de juguetes Informar el valor total de todos los juguetes que hay en la tienda Informar el valor promedio de los juguetes por tipo Informar el tipo del cual hay más juguetes Ordenar de menor a mayor la cantidad de existencias de juguetes por tipo. Ejemplo si hay 5 juguetes femeninos, 2 masculinos y 7 unisex, el ordenamiento quedaría como 2 masculino, 5 femenino y 7 unisex. Comenzar una nueva tienda de juguetes” el primer método que se va a construir es el método contarPorTipo. Este método requiere que el usuario ingrese el tipo deseado, por ello tipo se ha puesto como parámetro.
76
public void contarPorTipo(int tipo) { if(miJuguete.getTipo()==Juguete.FEMENINO) {contadorF++; } else if(miJuguete.getTipo()==Juguete.MASCULINO) {contadorM++; } else {contadorU++; } }
Es de anotar, que para solucionar el método contarPorTipo es necesario el uso de contadores. Un contador es una variable que se incrementa o decrementa en un valor fijo, en nuestro caso cada vez que se agrega un juguete uno de los tres contadores debe incrementarse en 1, dependiendo del juguete agregado.
El método determinarTipoMayor no requiere de parámetros puesto que ya se cuenta con datos suficientes para resolver el problema, a saber: el contador de juguetes de tipo femenino, el contador de juguetes de tipo masculino y el contador para juguetes de tipo unisex. public String determinarTipoMayor() { if(contadorF>contadorM&&contadorF>contadorU) { return "FEMENINO";} else if(contadorM>contadorF&&contadorM>contadorU) { return "MASCULINO";} else { return "UNISEX";} }
El método ordenar tiene una estructura muy similar al anterior. Este método requiere el uso de if anidados.
77
public String ordenar() { if(contadorF>contadorM&&contadorM>contadorU) { return " Femenino: "+contadorF+", Masculino: "+contadorM+", Unisex: "+contadorU; } else if(contadorF>contadorU&&contadorU>contadorM) { return " Femenino: "+contadorF+", Unisex: "+contadorU+", Masculino: "+contadorM; } else if(contadorM>contadorF&&contadorF>contadorU) { return " Masculino: "+contadorM+", Femenino: "+contadorF+", Unisex: "+contadorU; } else if(contadorM>contadorU&&contadorU>contadorF) { return " Masculino: "+contadorM+", Unisex: "+contadorU+", Femenino: "+contadorF; } else if(contadorU>contadorF&&contadorF>contadorM) { return " Unisex: "+contadorU+", Femenino: "+contadorF+", Masculino: "+contadorM; } else {return " Unisex: "+contadorU+", Masculino: "+contadorM+", Femenino: "+contadorF;} }
La instrucción if(contadorF>contadorM&&contadorM>contadorU) puede interpretarse como… Por ejemplo tengo 10 juguetes femeninos, 3 juguetes unisex, 5 juguetes masculinos. Entonces el ordenamiento correcto sería "Femenino: 10 Masculino: 5 Unisex: 3 ", puesto que contadorF que vale 10 es mayor que contadorM que vale 5 y contadorM que vale 10 es mayor que contadorU que vale 3
ACTIVIDAD 1. Basado en el caso de estudio anterior subraye en el código del método ordenar la instrucción que se ajusta a cada caso: - Se tienen 3 juguetes femeninos, 15 unisex y 7 masculinos. - Se tienen 5 juguetes masculinos, 2 femeninos y 1 femenino. 78
2. Consulte en Internet como funciona la estructura switch y modifique este caso de estudio para que haga uso de ella, al menos en un método. 3. Construya un método que permita obtener la información del juguete más económico que se haya agregado en la Tienda 2.3. Hoja de trabajo 1 Unidad II: Autoservicio Se desea crear una Aplicación para manejar la información de un autoservicio. En el autoservicio hay tanto empleados como productos. El autoservicio puede ofrecer máximo 3 productos. Cada producto posee un código, un nombre, un precio (no incluye iva) y una cantidad de existencias. También en el autoservicio hay 2 empleados. Cada empleado tiene un nombre, un código, una edad y un salario devengado. La aplicación debe permitir: Agregar un nuevo producto. Calcular el valor total de cada producto (para ello se debe solicitar al usuario el valor del iva) Indicar la cantidad de existencias que hay en el autoservicio, es decir, la suma de las existencias de los 3 productos Obtener el producto más económicos Agregar los empleados Informar si el promedio de edades de empleados de la empresa es superior a 30 años Devolver la información del empleado que devenga mayor salario Incrementar el salario del empleado especificado, siguiendo los siguientes criterios: Si el salario actual es menor a 700.000 el incremento es del 10% Si el salario actual es mayor o igual a 700.000 y menor de 1500.000 el incremento es del 15% De lo contrario el incremento es del 18%
2.3.1.
Comprensión del problema
a) Requisitos funcionales NOMBRE RESUMEN ENTRADAS
R1 – Calcular el valor total de cada producto Para calcular el valor del producto es necesario tener en cuenta el iva
RESULTADOS
NOMBRE RESUMEN
R2 - Indicar la cantidad de existencias que hay en el autoservicio La cantidad de existencias que hay en el autoservicio es la suma de las existencias de los 3 productos
ENTRADAS RESULTADOS
79
NOMBRE RESUMEN ENTRADAS
R3 - Obtener el producto más económico
RESULTADOS
NOMBRE
R4 - Informar si el promedio de edades de empleados de la empresa es superior a 30 años
RESUMEN ENTRADAS RESULTADOS
NOMBRE RESUMEN ENTRADAS
R5 - Devolver la información del empleado que devenga mayor salario
RESULTADOS
NOMBRE
RESUMEN
R6 - Incrementar el salario del empleado especificado Para incrementar el salario del empleado se siguen los siguientes criterios: - Si el salario actual es menor a 700.000 el incremento es del 10% - Si el salario actual es mayor o igual a 700.000 y menor de 1500.000 el incremento es del 15% - De lo contrario el incremento es del 18%
ENTRADAS RESULTADOS
b) Especificación de la Interfaz de usuario
Una parte importante del diseño de la solución es la especificación de la interfaz de usuario. La siguiente figura muestra el diseño seleccionado para este caso de estudio:
80
Ventana principal
Ventana para Consultas
La Ventana Principal de la aplicación está compuesta por 3 botones, cada uno de los cuales permite navegar por las diferentes zonas de la aplicación. El primero de ellos permite ingresar a la zona de registro de un nuevo empleado. El segundo permite ingresar cada uno de los 3 productos, para ello se solicita el código, el nombre, el precio y la cantidad de existencias por cada producto. El último botón permite la realización de las consultas, cada una de ellas asociada con un requisito funcional.
c) El modelo del mundo del problema Las clases identificadas son las siguientes:
ENTIDAD DEL MUNDO Autoservicio Empleado Producto
DESCRIPCIÓN Es la entidad más importante del mundo del problema. Es un atributo del autoservicio Es un atributo del autoservicio
Los métodos y atributos identificados son los siguientes:
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA PRODUCTO ATRIBUTO codigo nombre precio cantidadExistencias
VALORES POSIBLES Cadena de caracteres Cadena de caracteres Valor real positivo Valor entero positivo
81
Tipo de dato String String doble int
IDENTIFICACIÓN DE MÉTODOS Los métodos identificados son los siguientes: public Producto(String codigo, String nombre, double precio,int cantidadExistencias) public double obtenerValorTotalProducto(double iva) public String getNombre() public double getPrecio() public int getCantidadExistencias()
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA EMPLEADO ATRIBUTO nombre codigo salario edad
VALORES POSIBLES Cadena de caracteres Cadena de caracteres Valor real positivo Valor entero positivo IDENTIFICACIÓN DE MÉTODOS
Tipo de dato String String doble int
Es necesario construir los métodos set para cada uno de los atributos además de los siguientes métodos: public int getEdad() public double getSalario() public String getNombre() public void incrementarSalario()
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA AUTOSERVICIO ATRIBUTO miProducto0 miProducto1 miProducto2 miEmpleado0 miEmpleado1
VALORES POSIBLES
Tipo de dato
IDENTIFICACIÓN DE MÉTODOS Los métodos identificados son los siguientes: public void setMiProducto0(String codigo, String nombre, double precio,int cantidadExistencias)
public void setMiProducto1(String codigo, String nombre, double precio,int cantidadExistencias)
public void setMiProducto2(String codigo, String nombre, double precio,int cantidadExistencias)
public double calcularPrecioProducto(int numeroProducto, double iva ) public double calcularPrecioProducto(int numeroProducto, double iva ) public Producto hallarMasEconomico()
82
public void setMiEmpleado1(String nombre, String codigo, int edad, double salario)
public boolean informarPromedioSuperior30() public Empleado hallarEmpleadoMasSueldo() public Empleado incrementarSalario(int numeroEmpleado)
A continuación construya el diagrama de clases.
Para comenzar la construcción de la aplicación se iniciará con la clase Producto. En esta clase se requiere de un método para calcular el valor total de un producto. Este método requiere de un parámetro, el iva. public double obtenerValorTotalProducto(double iva) { }
En la clase Empleado se requiere la construcción del método incrementarSalario(). Para incrementar el salario del empleado se siguen los siguientes criterios: - Si el salario actual es menor a 700.000 el incremento es del 10% - Si el salario actual es mayor o igual a 700.000 y menor de 1500.000 el incremento es del 15% - De lo contrario el incremento es del 18% public void incrementarSalario() {
} 83
La clase Autoservicio requiere la creación de varios métodos. Entre ellos: - El método calcularPrecioProducto requiere que el usuario indique cual es el producto al cuál se le va a calcular el precio y el iva de dicho producto. public double calcularPrecioProducto(int numeroProducto, double iva ) { if(numeroProducto==0 && miProducto0!=null) { return miProducto0.obtenerValorTotalProducto(iva); } else //Complete
}
El método obtenerExistenciasTotales() permite obtener la cantidad de existencias totales. Este método no tiene parámetros. En este método se necesita declarar un acumulador que permita sumar la cantidad de existencias de cada uno de los productos. public int obtenerExistenciasTotales() {
}
El método hallarMasEconomico() permite hallar el producto más económico. Este método no tiene parámetros. public Producto hallarMasEconomico() { if(miProducto0!=null &&((miProducto1!=null&&miProducto0.getPrecio()<miProducto1.getPrecio()) ||miProducto1==null)&&((miProducto2!=null&&miProducto0.getPrecio()<miProd ucto2.getPrecio())||miProducto2==null)) {return miProducto0;} else if(miProducto1!=null &&((miProducto0!=null&&miProducto1.getPrecio()<miProducto0.getPrecio()) || miProducto0==null)&&((miProducto2!=null&&miProducto1.getPrecio()<miProduc to2.getPrecio())||miProducto2==null)) {return miProducto1;} else if(miProducto2!=null) 84
{return miProducto2;} else return null; }
El método hallarEmpleadoMasSueldo() no requiere parámetros. En él hay que comparar los salarios de los empleados para saber cuál de los dos empleados gana más. public Empleado hallarEmpleadoMasSueldo() {
}
Finalmente, el método incrementarSalario requiere de un parámetro, numeroEmpleado, que informa a cuál empleado se le va a incrementar el salario. public Empleado incrementarSalario(int numeroEmpleado) { if(numeroEmpleado==0) { miEmpleado0.incrementarSalario(); return miEmpleado0; } else { miEmpleado1.incrementarSalario(); return miEmpleado1; } }
2.4. Caso de estudio 2 Unidad II: Concesionario Se desea crear una aplicación para manejar la información de un concesionario. El concesionario tiene para la exhibición siempre tres vehículos, cada uno de ellos con placa, marca, tipo (0Carro 1 Moto) y una fecha de registro ante la oficina de tránsito. La aplicación debe permitir: Identificar la marca de los vehículos que más se repite. El tipo de vehículo menos repetido (0Carro 1 Moto) Identificar para un vehículo determinado si debe contar con certificado técnico mecánico. Es de anotar que si el vehículo es un carro debe tener certificado a partir de los 2 años, si es una moto a partir del año.
85
2.4.1.
Comprensión del problema
a) Requisitos funcionales NOMBRE RESUMEN
R1 – Identificar la marca de los vehículos que más se repite Se debe examinar cada una de las marcas de los vehículos para saber cuál es la que más se repite
ENTRADAS Ninguna RESULTADOS La marca
NOMBRE RESUMEN
R2 – El tipo de vehículo menos repetido (0Carro 1 Moto) Se debe examinar cada uno de los tipos de los vehículos para verificar cuál es el que menos se presenta.
ENTRADAS Ninguna RESULTADOS El tipo menos repetido NOMBRE RESUMEN
R3 – Identificar para un vehículo determinado si debe contar con certificado técnico mecánico Es de anotar que si el vehículo es un carro debe tener certificado a partir de los 2 años, si es una moto a partir del año.
ENTRADAS Ninguna RESULTADOS La indicación de si debe o no tener certificado
2.4.2. Especificación de la Interfaz de usuario Una parte importante del diseño de la solución es la especificación de la interfaz de usuario. La siguiente figura muestra el diseño seleccionado para este caso de estudio:
86
La ventana de la aplicación está dividida en 2 zonas: La primera de ellas permite ingresar la información de cada vehículo. Cuando se da clic en cualquiera de los tres botones iniciales, una nueva ventana es desplegada. En esta última se solicitan la placa, la marca, el tipo y la fecha de matrícula. En la segunda zona hay 3 botones, cada uno de ellos asociado a un requisito funcional.
2.4.3.Otros elementos de modelado
Un nuevo elemento de modelado que se incorpora en este caso de estudio es el enum. Un tipo enumerado es usado para restringir el contenido de una variable a una lista de valores predefinidos. En el caso de estudio del Concesionario es posible definir un enum para el tipo en lugar de utilizar constantes tal como se hizo en el caso de estudio anterior. public enum Tipo { //Tipos de vehículos disponibles CARRO (0), MOTO (1); private int numTipo; private Tipo(int numTipo) { this.numTipo = numTipo; } public int getNumTipo() { return numTipo; } }
87
Un tipo enumerado es una instancia del tipo enumerado del que es declarado, por ello no puede considerarse como un String o un entero. Un enum también puede ir embebido dentro de una clase. Tal como se muestra a continuación: public class Vehiculo { public enum Tipo { //Tipos de vehículos disponibles CARRO (0), MOTO (1); private int numTipo; private Tipo(int numTipo) { this.numTipo = numTipo; } public int getNumTipo() {return numTipo;}} private String placa,marca; private int tipo; private Fecha miFechaRegistro; }
b) El modelo del mundo del problema Las actividades que se deben realizar para construir el modelo del mundo son las siguientes: Identificar las entidades o clases.
ENTIDAD DEL MUNDO Concesionario Vehiculo Fecha
DESCRIPCIÓN Es la entidad más importante del mundo del problema. Es un atributo del concesionario Es un atributo de la Fecha
Identificar los métodos
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA FECHA ATRIBUTO dia mes anio
VALORES POSIBLES Valor entero positivo Valor entero positivo Valor entero positivo IDENTIFICACIÓN DE MÉTODOS
Tipo de dato int int int
(Se brindarán dos opciones para crear la fecha: un constructor para crear la fecha actual y otro con parámetros para iniciar la fecha con los valores dados por el usuario) public Fecha() public Fecha(int dia, int mes, int anio)
Adicionalmente se requieren los métodos get para cada atributo. También se necesita un método que permita calcular la diferencia entre dos fechas public int restarFechaALaPrimera( Fecha segunda, int tipo )
88
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA VEHICULO ATRIBUTO placa marca tipo miFechaRegistro
VALORES POSIBLES Cadena de caracteres Cadena de caracteres Valor entero positivo Referencia a un objeto de tipo Fecha
Tipo de dato String String int Fecha
IDENTIFICACIÓN DE MÉTODOS (para crear un Vehiculo se debe crear un método set para para cada uno de los atributos) public void setPlaca(String placa) public void setMarca(String marca) public void setTipo(int tipo) public void setMiFechaRegistro(int dia, int mes, int anio) Para cada uno de los atributos también es necesaria la creación de los métodos get.
Las Relaciones entre las clases del mundo
89
La forma apropiada de empezar a construir el código de esta aplicación es iniciando por la clase Fecha, pues ésta no depende de ninguna otra. El constructor de Fecha que no tiene parámetros permite crear una referencia un objeto de tipo Fecha con la fecha actual.
public Fecha() { //Se obtiene la fecha actual GregorianCalendar miFechaActual = new GregorianCalendar( ); // Sacamos los valores de día, mes y año del calendario anio = miFechaActual.get( Calendar.YEAR ); mes = miFechaActual.get( Calendar.MONTH ) + 1; dia = miFechaActual.get( Calendar.DAY_OF_MONTH ); } Para restar dos fechas se ha creado un método que tiene dos parámetros. El primero recibe la fecha que se va a restar de la primera fecha y el segundo, recibe el tipo de diferencia requerida, si el valor es 0 es porque se requiere una diferencia en meses, pero si es uno se necesita en años.
//tipo 0 diferencia en meses, 1 en años public int restarFechaALaPrimera( Fecha segunda, int tipo ) { // Se determina cuantos meses hay de diferencia int diferencia = 12 * ( segunda.getAnio() - anio ) + ( segunda.getMes() - mes ); diferencia=-diferencia; //Se resta un mes en caso de que el día no sea mayor if( segunda.getDia() < dia ) diferencia--; if(tipo==1) diferencia=diferencia/12; return diferencia; }
A continuación se procede con la clase Vehiculo. En la clase Vehiculo se construye por cada atributo un método get. Entre estos métodos se tiene a: public void setMiFechaRegistro(int dia, int mes, int anio) { this.miFechaRegistro = new Fecha(dia, mes, anio); }
Otro método muy útil es el método toString, que devuelve un String con la representación del objeto.
90
public String toString() { return "Placa "+placa + ", Marca: "+marca+", "+miFechaRegistro.toString()+ ", Tipo: "+Tipo.values()[tipo]; }
Observe que en el método toString se imprime el tipo del vehículo, a través de la instrucción Tipo.values()[tipo]. La cual se puede interpretar de la siguiente forma basados en la enumeración que se muestra a continuación: public enum Tipo { //Tipos de vehículos disponibles CARRO (0), MOTO (1); private int numTipo; private Tipo(int numTipo) { this.numTipo = numTipo; } public int getNumTipo() { return numTipo; } }
Si tipo toma el valor de cero, entonces Tipo.values()[0] devolverá CARRO, pero si toma el valor de 1, Tipo.values()[1] devolverá MOTO. En la clase Concesionario es necesario trabajar el método determinarCertificadoTecnicoMecanico. Este método recibe un vehículo. Para realizar el cálculo lo primero que debe hacerse es calcular la fecha actual y a ésta restarle la fecha en que el vehículo se registró ante la secretaría de tránsito. public boolean determinarCertificadoTecnicoMecanico(Vehiculo miVehiculo) { if(miVehiculo!=null) { Fecha miFecha=new Fecha(); int antiguedad=miFecha.restarFechaALaPrimera(miVehiculo.getMiFechaRegistro(), 1); //si es carro if (miVehiculo.getTipo()==0) { if(antiguedad>=2) {return true;} else {return false;} }//Cierra if carro else { if(antiguedad>=1) {return true;} else {return false;}
91
}//Cierra else de moto }//Cierra if de miVehiculo!=null return false; }
Para hallar la marca que más se repite se crearon dos métodos, el primero tiene un parámetro, marca, que permite saber la cantidad de vehículos del concesionario que poseen dicha marca. public int contarMarca(String marca) { int contador=0; if(marca.equals(miVehiculo0.getMarca())) {contador++;} if(marca.equals(miVehiculo1.getMarca())) {contador++;} if(marca.equals(miVehiculo2.getMarca())) {contador++;} return contador; }
En el segundo, se invoca el método anterior, enviando como argumento uno de los vehículos según se requiera.
public String hallarMarcaMasRepite() { if(miVehiculo0!=null&&miVehiculo1!=null&&miVehiculo2!=null) { if(contarMarca(miVehiculo0.getMarca())>=contarMarca(miVehiculo1.getMarca( ))&&contarMarca(miVehiculo0.getMarca())>=contarMarca(miVehiculo2.getMarca ())) {return miVehiculo0.getMarca();} else if(contarMarca(miVehiculo1.getMarca())>=contarMarca(miVehiculo0.getMarca( ))&&contarMarca(miVehiculo1.getMarca())>=contarMarca(miVehiculo2.getMarca ())) {return miVehiculo1.getMarca();} else {return miVehiculo2.getMarca();} }// Cierra el if en el que se verifica que los vehículos no sean null else return "Debe ingresar primero los tres vehiculos"; }
2.5. Hoja de Trabajo 2 Unidad II: Floristería Se desea crear una aplicación para manejar la información de una floristería. En la floristería se hacen 4 pedidos (cada uno de ellos con una cantidad y un tipo asignado). Un tipo está formado por un nombre de la flor (0 Rosas, 1 Tulipanes, 2 Girasoles o 3 Crisantemos) y una valoración dada (0Calidad de exportación ó 1 Calidad normal).
92
La aplicación debe permitir calcular el valor total de los 4 pedidos si se sabe que el valor unitario por flor es: Si es Rosas Calidad de exportación el valor unitario es 4000 pesos Tulipanes Calidad de exportación, el valor unitario es de 3200 Girasoles Calidad de exportación, el valor unitario es de 3500 Crisantemos Calidad de exportación, el valor unitario es de 2200 El precio de las flores calidad normal es del 70% del precio de la flor calidad exportación de su categoría. De igual forma se debe permitir obtener: La cantidad de productos por nombre de flor (Rosas, Tulipanes, Girasoles, Crisantemos) que hay en la floristería La cantidad de productos por nombre de Flor y valoración especifica que hay en la floristería El nombre de la flor con más cantidad de flores en toda la floristería Informar si el precio total de un pedido particular excede los 200000
2.5.1.
Comprensión del problema
a) Requisitos funcionales NOMBRE RESUMEN ENTRADAS
R1 – Calcular el valor total de los pedidos
RESULTADOS
NOMBRE RESUMEN ENTRADAS
R2 – Obtener la cantidad de productos por nombre de flor
RESULTADOS
NOMBRE
R3 – Obtener la cantidad de productos por nombre de Flor y valoración especifica que hay en la floristería
RESUMEN ENTRADAS RESULTADOS
93
NOMBRE RESUMEN ENTRADAS
R4 - El nombre de la flor con más cantidad de flores en toda la floristería
RESULTADOS
NOMBRE RESUMEN ENTRADAS
R5 - Informar si el precio total de un pedido particular excede los 200000
RESULTADOS
b) Especificación de la Interfaz de usuario Una parte importante del diseño de la solución es la especificación de la interfaz de usuario. La siguiente figura muestra el diseño seleccionado para este caso de estudio:
La ventana está dividida en dos zonas. La primera de ellas es la zona de ingreso de los pedidos. La segunda zona permite realizar todas las consultas, cada uno de los botones está asociado con un requisito funcional.
94
c) El modelo del mundo del problema Las clases identificadas son las siguientes:
ENTIDAD DEL MUNDO Floristeria Pedido Tipo
DESCRIPCIÓN Es la entidad más importante del mundo del problema. Es un atributo de la Floristeria Es un atributo del Pedido
Los métodos y atributos identificados son los siguientes:
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA TIPO ATRIBUTO nombreFlor valoración public public public public
VALORES POSIBLES Valor entero positivo Valor entero positivo IDENTIFICACIÓN DE MÉTODOS
Tipo de dato int int
Tipo(int tipo, int valoración) int getNombreFlor() int getValoración() double calcularValorUnitario()
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA PEDIDO ATRIBUTO
VALORES POSIBLES
cantidad miTipo IDENTIFICACIÓN DE MÉTODOS public public public public public public
Pedido(int cantidad) int getCantidad() void setCantidad(int cantidad) void setMiTipo(int nombreFlor, int valoración) double calcularValorTotalPedido() boolean determinarExcede()
95
Tipo de dato
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA FLORISTERÍA ATRIBUTO miPedido0 miPedido1 miPedido2 miPedido3
VALORES POSIBLES
Tipo de dato
IDENTIFICACIÓN DE MÉTODOS public void setMiPedido(int numPedido,int cantidad,int nombre, int valoración) public double calcularValorTotal4Pedidos() public double obtenerCantidadPorNombreFlor(int nombreFlor) public double obtenerCantidadPorNombreFlorYValoracion(int nombreFlor, int valoracion) public String obtenerNombreCategoriaConMasFlores() public boolean informarExcede(int numPedido)
A continuación construya el diagrama de clases.
96
2.5.2. Asociaciones opcionales Si se quisiera modificar el enunciado del caso de estudio anterior para indicar que pueden haber 1 o 2 empleados, serรก necesario hacer uso de la cardinalidad, esto se logra indicando que las asociaciones pueden existir o no. Tal como se muestra en el diagrama de clases siguiente:
97
En el siguiente diagrama de objetos se aprecian asociaciones opcionales.
miFloristeria: Floristeria
miPedido0
: Pedido
miPedido1=null miPedido2=null miPedido3=null
Diagrama de objetos donde se aprecian asociaciones opcionales
2.6. Tipos de métodos Los métodos se clasifican en: Métodos constructores, los cuales permiten inicializar los atributos de un objeto al momento de reservarle memoria. Métodos modificadores (setter), los cuales permiten modificar el estado de los objetos, durante la ejecución. Métodos accesores (getter), los cuales permiten obtener el valor de algún atributo de un objeto. Métodos analizadores quienes tiene como responsabilidad el “saber hacer”, pues gracias a ellos es posible calcular información valiéndose del estado de los objetos.
Actividad Complete el código para las clases de la hoja de trabajo de la Floristería. public public public public public public public
class Tipo static int static int static int static int static int static int
{ NOMBRE_ROSAS=0; NOMBRE_TULIPANES=1; NOMBRE_GIRASOLES=2; NOMBRE_CRISANTEMOS=3; VALORACION_EXPORTACION=0; VALORACION_NORMAL=1;
private int nombreFlor; private int valoracion; 98
public Tipo(int tipo, int valoracion) { } public int getNombreFlor() { } public int getValoracion() { return valoracion; } public double calcularValorUnitario() { double precio=0; if(nombreFlor==NOMBRE_ROSAS&&valoracion==VALORACION_EXPORTACION) { precio= 4000; }
} }
public class Pedido { private int cantidad; private Tipo miTipo; public Pedido(int cantidad) { } public int getCantidad() {
} public void setCantidad(int cantidad) { this.cantidad = cantidad; } 99
public Tipo getMiTipo() { return miTipo; } public void setMiTipo(int nombreFlor, int valoracion) { this.miTipo = new Tipo(nombreFlor,valoracion); } public double calcularValorTotalPedido() { return cantidad*miTipo.calcularValorUnitario(); } public boolean determinarExcede() {
}
public class Floristeria { private Pedido miPedido0, miPedido1, miPedido2, miPedido3; public Floristeria() { miPedido0=new Pedido(0); miPedido1=new Pedido(0); miPedido2=new Pedido(0); miPedido3=new Pedido(0); } public double calcularValorTotal4Pedidos() {
} public double obtenerCantidadPorNombreFlor(int nombreFlor) { double acum=0;
100
} public double obtenerCantidadPorNombreFlorYValoracion(int nombreFlor, int valoracion) { double acum=0; if(miPedido0.getMiTipo().getNombreFlor()==nombreFlor&&miPedido0.getMiTipo ().getValoracion()==valoracion) { acum+=miPedido0.getCantidad(); } if(miPedido1.getMiTipo().getNombreFlor()==nombreFlor&&miPedido1.getMiTipo ().getValoracion()==valoracion) { acum+=miPedido1.getCantidad(); } if(miPedido2.getMiTipo().getNombreFlor()==nombreFlor&&miPedido2.getMiTipo ().getValoracion()==valoracion) { acum+=miPedido2.getCantidad(); } if(miPedido3.getMiTipo().getNombreFlor()==nombreFlor&&miPedido3.getMiTipo ().getValoracion()==valoracion) { acum+=miPedido3.getCantidad(); } return acum; } public { double double double double
String obtenerNombreCategoriaConMasFlores() a=obtenerCantidadPorNombreFlor(Tipo.NOMBRE_ROSAS); b=obtenerCantidadPorNombreFlor(Tipo.NOMBRE_GIRASOLES); c=obtenerCantidadPorNombreFlor(Tipo.NOMBRE_CRISANTEMOS); d=obtenerCantidadPorNombreFlor(Tipo.NOMBRE_TULIPANES);
if(a>=b&&a>=c&&a>=d) { return "Rosas" ; }
101
} public boolean informarExcede(int numPedido) { Pedido inicializado=detectarPedido(numPedido); return inicializado.determinarExcede(); }}
102
3.
ESTRUCTURAS CONTENEDORAS
Objetivos Al finalizar la unidad el estudiantes estará en capacidad de: Utilizar estructuras contenedoras de tamaño fijo para resolver problemas en los cuales es necesario almacenar una secuencia de elementos Utilizar ciclos para poder manipular las estructuras contenedoras fijas Construir interfaces gráficas que involucren la utilización de estructuras contenedoras de tamaño fijo.
3.1. Caso de estudio 1Unidad III: Grupo de estudiantes Un docente requiere de una aplicación para manejar la información de un grupo en el cual hay como máximo 6 estudiantes, cada uno de ellos con código, nombre y una asignatura. De cada asignatura se conocen dos notas parciales. Se debe permitir calcular la nota promedio del curso Informar cuántos estudiantes obtuvieron nota en el rango especificado: 0 y 2..99 3 y 3.99 4y5 Informar cuántos estudiantes ganaron la asignatura
103
3.1.1.
Comprensión del problema
a) Requisitos funcionales NOMBRE RESUMEN
R1 – Calcular la nota promedio del curso Se suman todas las notas de los estudiantes y se divide por el número de estudiantes.
ENTRADAS Ninguna RESULTADOS La nota promedio
NOMBRE RESUMEN
R2 – Informar cuántos estudiantes obtuvieron nota en el rango especificado Existen 3 rangos: 0 y 2..99 3 y 3.99 4y5
ENTRADAS El rango RESULTADOS La cantidad de estudiantes con nota en el rango indicado
NOMBRE R3 – Informar cuántos estudiantes ganaron la asignatura RESUMEN ENTRADAS Ninguna RESULTADOS La cantidad de estudiantes que ganaron la asignatura
b) El modelo del mundo del problema Las actividades que se deben realizar para construir el modelo del mundo son: Identificar las entidades o clases.
ENTIDAD DEL MUNDO Grupo Estudiante Asignatura
DESCRIPCIÓN Es la entidad más importante del mundo del problema. Es un atributo del Grupo Es un atributo del Estudiante
Identificar los atributos y los métodos.
104
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA ASIGNATURA ATRIBUTO nota1 nota2 public public public public public public
VALORES POSIBLES Valores reales positivos Valores reales positivos IDENTIFICACIÓN DE MÉTODOS
Tipo de dato double double
Asignatura(double nota1, double nota2) double calcularDefinitiva() double getNota1() void setNota1(double nota1) double getNota2() void setNota2(double nota2)
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA ESTUDIANTE ATRIBUTO codigo nombre miAsignatura0 public public public public public
VALORES POSIBLES Cadena de caracteres Cadena de caracteres Referencia a objeto de tipo Asignatura IDENTIFICACIÓN DE MÉTODOS
Tipo de dato String String Asignatura
Estudiante(String codigo, String nombre) String getCodigo() String getNombre() void setMiAsignatura0(double nota1, double nota2) boolean isGanador()
IDENTIFICACIÓN Y MODELAMIENTO DE ATRIBUTOS PARA GRUPO ATRIBUTO misEstudiantes
public public double public public public
VALORES POSIBLES Arreglo de referencias a objetos de tipo estudiante IDENTIFICACIÓN DE MÉTODOS
Tipo de dato Estudiante []
Grupo() void agregarEstudiante(int posicion, String codigo, String nombre, nota1, double nota2) double calcularPromedio() int contarRango(int rango) int contarEstudiantesGanaron()
105
3. Las Relaciones entre las clases del mundo
Para iniciar la construcción de esta aplicación se inicia por la clase Asignatura. En esta clase es necesario realizar el método calcularDefinitiva. Este método no tiene parámetros. public double calcularDefinitiva() { return (nota1+nota2)/2; }
En la clase Estudiante se requiere el método isGanador() que permite identificar si el estudiante ganó o perdió la asignatura public boolean isGanador() { if(miAsignatura0.calcularDefinitiva()>=3) { return true; } else {return false;} }
Dado que en la clase Grupo se necesita manejar la información de un listado de estudiantes, se requiere la incorporación del concepto de estructuras contenedoras de tamaño fijo, más conocidas como arreglos.
106
Los arreglos son un tipo de estructura contenedora, que permite agrupar elementos del mismo tipo de datos, por ejemplo un grupo de estudiantes, una lista de productos y un grupo de empleados. A todo arreglo se le debe declarar y reservarle memoria antes de empezar a usarlo. La forma de declarar un arreglo es la siguiente: Primero va el tipo de dato y luego nombre. Por ejemplo: Estudiante[] misEstudiantes; //Se declara misEstudiantes=new Estudiante[6]; //Se reserva memoria Como puede verse en la línea de la declaración, se hizo uso del operador de indexación “[]”. Esta sintaxis permite especificar que se va a almacenar una lista de elementos del mismo tipo. Este operador permite tener acceso a cada uno de los elementos de la estructura contenedora escribiendo primero el nombre del arreglo, seguido de los corchetes que tendrán en su interior un índice, variable de tipo entero, que indicará la posición a la cual se desea tener acceso. Por ejemplo, si se desea acceder al elemento del arreglo misEstudiantes que se encuentra en la posición 3 se escribiría misEstudiantes[3]; Observe que para poder reservarle memoria al arreglo se hizo uso del operador new. Es importante resaltar que la declaración y creación del arreglo se pueden hacer en una sola línea.
Estudiante[] misEstudiantes = new Estudiante[6]; ó Estudiante misEstudiantes[] = new Estudiante[6]; Es de anotar que si el arreglo no es de tipo de datos primitivo, será necesario además de reservarle memoria al arreglo, reservarle memoria a cada uno de los elementos que el arreglo va a contener. Una estructura contenedora puede tener una o más dimensiones. En este material solo se trabajarán con estructuras unidimensionales. Para poder recorrer y manipular los elementos almacenados en una estructura de este tipo es necesario hacer uso de estructuras repetitivas. Una estructura repetitiva se utiliza cuando se necesita que una serie de instrucciones se ejecuten un número determinado de veces. Toda estructura repetitiva consta de tres partes básicas, a saber:
Decisión: en esta parte se evalúa la condición y, en caso de ser cierta, se ejecuta el ciclo.
Cuerpo del ciclo: en esta parte van las instrucciones que se desea ejecutar varias veces.
Salida del ciclo: es la condición que indica cuando termina de ejecutarse el ciclo, es decir, que ya no se repetirán más las instrucciones.
107
Normalmente los ciclos se controlan mediante una variable denominada contador, que incrementa o decrementa su valor en un valor fijo cada vez que se efectúa una repetición. Es muy común también encontrar en los ciclos variables acumuladoras, que permiten almacenar una cantidad variable, resultado de operaciones repetidas y sucesivas. La estructura repetitiva más usada para trabajar con arreglos es el ciclo for. El for tiene la siguiente estructura:
for ( inicialización; condicion; iteración) { acción 1 ........ acción n
}
Lo primero que se ejecuta es la inicialización, que normalmente lleva una expresión de asignación dirigida hacia un contador (variable de control) del ciclo. Esta expresión se ejecuta solamente una vez. Luego se evalúa la condición, que debe dar como resultado una expresión booleana. Si la comparación da como resultado true, entonces se ejecuta el cuerpo del ciclo. De lo contrario, el ciclo finaliza. A continuación se efectúa la iteración, en la que normalmente se incrementa o decrementa la variable de control del ciclo. Es importante que tenga en cuenta que en cada pasada del ciclo, se evalúa de nuevo la expresión condicional, se ejecuta el cuerpo del ciclo y se continúa con la iteración. Esto se efectuará hasta que la condición sea falsa. Ahora bien, el concepto de ciclos aplicado en los arreglos permitirá recorrer dichas estructuras contenedoras, partiendo desde la posición cero hasta la totalidad de elementos que se encuentren almacenados. Esto no quiere decir que no pueda recorrerse en un orden diferente. Para lograr dicho objetivo se deberá declarar un índice que permita manejar la posición a la cual se desea tener acceso. Retomando el caso de estudio del Colegio, se tiene entonces que se requiere un método constructor. En este método es necesario reservarle memoria al arreglo de estudiantes. public Grupo() { // MAXIMO_ESTUDIANTES es una constante con valor de 6 misEstudiantes=new Estudiante[MAXIMO_ESTUDIANTES]; }
108
También se debe crear un método para agregar cada uno de los estudiantes. Este método además de todos los datos necesarios para crear el estudiante, necesita saber la posición del estudiante que se va a almacenar. public void agregarEstudiante(int posicion, String codigo, String nombre, double nota1, double nota2) { Estudiante miE=new Estudiante(codigo, nombre); miE.setMiAsignatura0(nota1, nota2); misEstudiantes[posicion]=miE; } El método calcularPromedio no requiere parámetros, pues con el listado de estudiantes es suficiente para realizar dicho cálculo. En este método es necesario declarar a i (índice para moverse a través del arreglo), un contador para saber cuántos estudiantes hay y un acumulador para poder almacenar la sumatoria de las definitivas de cada estudiante. Observe que el for se efectúa seis veces. En cada ejecución verifica que se haya almacenado un estudiante. Si es afirmativo, obtiene su nota definitiva y la almacena en el acumulador y simultáneamente incrementa el contador para indicar que en ese espacio hay un estudiante. Al final divide el acumulador, sumatoria de las notas definitivas, por el contador de estudiantes. public double calcularPromedio() { double acumulador=0; int contador=0; for(int i=0; i<MAXIMO_ESTUDIANTES;i++) { if(misEstudiantes[i]!=null) { acumulador+=misEstudiantes[i].getMiAsignatura0().calcularDefinitiva(); contador++; } } return acumulador/contador; } El método para determinar cuántos estudiantes obtuvieron nota definitiva en el rango especificado recibe como parámetro una variable de tipo entero llamada rango. Si el valor de rango es 0 se está solicitando el rango entre 0 y 2.99, si su valor es 1 se pide el rango entre 3 y 3.9. Si el valor es 2 es el rango entre 4 y 5. La variable rango determina el punto de inicio y de finalización del for. public int contarRango(int rango) { double inicia=0, finaliza=3; int contador=0; if(rango==1) { inicia=3; finaliza =4; } else if(rango==2) {inicia=4; finaliza=5.01; } for(int i=0; i<MAXIMO_ESTUDIANTES; i++) {
109
if(misEstudiantes[i]!=null&&misEstudiantes[i].getMiAsignatura0().calcular Definitiva()>=inicia&&misEstudiantes[i].getMiAsignatura0().calcularDefini tiva()<finaliza) { contador++; } } return contador; }
El último método requerido es el método contarEstudiantesGanaron(), que no requiere parámetros. En este método se necesita declarar el índice y además un contador. Observe que siempre se verifica que en la posición i haya un estudiante, esto con el objetivo de que no se produzca la excepción NullPointerException. public int contarEstudiantesGanaron() { int contador=0; for(int i=0; i<MAXIMO_ESTUDIANTES; i++) { if(misEstudiantes[i]!=null&&misEstudiantes[i].isGanador()==true) { contador++; } }//Finaliza el for return contador; }
3.2. Hoja de Trabajo 1 Unidad III: VideoTienda Se desea crear una aplicación para una videotienda. En ella se alquilan películas. Cada película tiene asociado un código, un nombre, una cantidad de existencias en bodega, un género (acción, terror, infantil, drama y un listado de actores, máximo 5. Cada actor tiene un cedula y un nombre. Se debe permitir: Ingresar un actor (se debe validar que no se ingresen actores que ya hayan sido ingresados) Ingresar una película (se debe validar que no se ingresen películas que ya hayan sido ingresadas) Prestar una película a un usuario (verificar que haya existencias disponibles). Se debe buscar por el código de la película. Es de anotar, que un usuario tiene un código y un nombre. Agregar un usuario Listar las películas que un usuario tiene prestadas. Listar los protagonistas de una determinada película Listar las películas de un determinado protagonistas, para ello se solicita el código del protagonista Mostrar la película más prestada
110
3.2.1.
Comprensión del problema
a) Requisitos funcionales NOMBRE RESUMEN ENTRADAS
R1 – Prestar una película a un usuario
RESULTADOS
NOMBRE
R2 – Listar las películas que un usuario tiene prestadas
RESUMEN ENTRADAS RESULTADOS
111
NOMBRE
R3 – Listar los protagonistas de una determinada película
RESUMEN ENTRADAS RESULTADOS
NOMBRE
R4 – Listar las películas de un determinado protagonistas
RESUMEN ENTRADAS RESULTADOS
NOMBRE
R5 – Mostrar la película más prestada
RESUMEN ENTRADAS RESULTADOS
b) El modelo del mundo del problema Algunas de las actividades que se deben realizar para construir el modelo del mundo son: Identificar las entidades o clases.
ENTIDAD DEL MUNDO VideoTienda Prestamo Pelicula
DESCRIPCIÓN
Identificar las relaciones entre las clases del mundo
112
113
Algunos de los métodos de la clase VideoTienda son: listarProtagonistasPelicula permite listar todos los protagonistas de una película, para ello el usuario debe indicar la posición donde está ubicada la película dentro del array de películas. El método devuelve un array de String con todos los protagonistas de la película. public String[] listarProtagonistasPelicula(int posicion) { String salida[]=new String[5]; Pelicula miPelicula=misPeliculas[posicion]; for(int i=0; i< miPelicula.getContadorActores();i++) { salida[i]=miPelicula.getMisActores()[i].toString(); } return salida; }
El método listarPeliculasPrestadasPorUsuario permite listar las películas que un usuario tiene prestadas, para ello se debe indicar la posición donde está ubicado el usuario dentro del array de usuarios. public String[] listarPeliculasPrestadasPorUsuario(int posicion) { /*Obtenga primero el usuario y a continuación recorra el arreglo de préstamos buscando ese usuario*/
}
114
El método listarPeliculasProtagonista permite listar las películas que un actor ha protagonizado, para ello se debe indicar la posición que el actor ocupa dentro del arreglo de protagonistas. public String[] listarPeliculasProtagonista(int posicionActor) { /*Primero obtenga el actor. Debe realizar dos for. El primero para recorrer el arreglo de películas y el segundo para recorrer por cada película el arreglo de actores. */ for(int i=0; i<contadorPeliculas; i++) { for(int j=0; j<misPeliculas[i].getContadorActores();j++) {
} } return peliculas; }
El método devolverCantidadDvdPrestadosPorPelicula recibe el código de la película y a través de un for que permite recorrer el arreglo de préstamos permite buscar la película. Si la encuentra el contador se incrementa. public int devolverCantidadDvdPrestadosPorPelicula(String codigo) { int contador=0;
}
115
El método prestarPelicula permite prestar una película. Tiene dos parámetros posicionP y posicionCliente. posicionP es la posición de la película dentro del arreglo de películas y posicionCliente es la posición del cliente dentro del arreglo de clientes. Para prestar la película es necesario verificar que haya existencias de la película y que el cliente ya no tenga en su poder una existencia de esa mismas película. public boolean prestarPelicula(int posicionP, int posicionCliente ) { /** * Se debe obtener la pelicula y el cliente, al igual que la cantidad de dvds prestados por esa pelicula. Es importante tener en cuenta que si solo hay por ejemplo 3 dvds de esa pelicula y ya todos estan prestados no podrá prestar mas. De igual forma se verifica que ese prestamo no haya sido efectuado ya, eso quiere decir que si el cliente con codigo 123 presto la pelicula 45, entonces este cliente no podrá volver a prestar esa pelicula */ Pelicula miPeli=misPeliculas[posicionP]; Cliente miCliente=misClientes[posicionCliente]; int cantidadPrestamos=devolverCantidadDvdPrestadosPorPelicula(miPeli.getCodigo()); if(cantidadPrestamos<miPeli.getCantidadDeExistencias()&&verificarYaExistePrestamo (miPeli, miCliente)==false) { Prestamo miP = new Prestamo(miPeli, miCliente); misPrestamos[contadorPrestamos]=miP; contadorPrestamos++; return true; } return false; }
El método verificarYaExistePrestamo permite verificar si una película ya ha sido prestada a un cliente. Se debe verificar esto porque un cliente solo tiene permitido alquilar una copia de una determinada película. Tiene dos parámetros: miPelicula y miCliente. public boolean verificarYaExistePrestamo(Pelicula miPelicula, Cliente miCliente) { /*Se recorre el array de prestamos y se verifica si el usuario tiene prestada la película se retorne true si es asi, de lo contrario false*/ for(int i=0; i<contadorPrestamos; i++) { if(misPrestamos[i].getMiPelicula().getCodigo().equals(miPelicula.getCodig o())&& misPrestamos[i].getMiCliente().getCodigo().equals(miCliente.getCodigo())) { return true;} } return false; }
116
El método devolverPeliculaMasPrestada() no tiene parámetros. Este método requiere el uso de un for. En el interior del for se invoca el método devolverCantidadDvdPrestadosPorPelicula. public Pelicula devolverPeliculaMasPrestada() { Pelicula masPrestada=null; int mayor=0, cantidadPrestamosPelActual=0;
return masPrestada; }
3.3. Caso de estudio 2 Unidad III: Parqueadero Se desea crear una aplicación para la administración de un parqueadero. El parqueadero está formado por 30 puestos. Los 12 primeros destinados a motos y los restantes a carros. Cada puesto tiene un número, un tipo (0 Vehículo Particular, 1 Moto) y un estado (0 libre 1 Ocupado). Para poder asignar un espacio dentro del parqueadero cuando un vehículo llega su propietario debe informar la placa del vehículo y el modelo, por su parte el administrador del sistema debe registrar la hora y fecha de ingreso manualmente o seleccionar la fecha actual del sistema. Es muy importante que cuando llegue el propietario del vehículo a retirar su moto o carro se le informe cuanto debe pagar, para ello se debe tener en cuenta la fecha y hora de salida del vehiculo, al igual que el tipo de vehiculo, pues si es moto el valor de la hora es 600 mientras que si es carro es de 1200. Es importante tener en cuenta que si al calcular la diferencia en horas y minutos entre las dos fechas, la cantidad de minutos es inferior a 6 minutos no se le cobrará una hora más, de lo contrario sí. Ejemplo, si son 5 horas y 10 minutos, se deberán cobrar 6 horas, pero si son 4 horas y 3 minutos se cobrarán solo cuatro horas.
117
3.3.1.
Comprensión del problema
a) Requisitos funcionales NOMBRE R1 – Ubicar un vehículo dentro del parqueadero RESUMEN El usuario ingresa la placa, el modelo, el tipo y la fecha y hora de ingreso ENTRADAS La placa, el modelo y el tipo de vehículo. También la hora y fecha de ingreso RESULTADOS Al vehículo se le ha asignado un puesto en el parqueadero
118
NOMBRE
RESUMEN
R2 – Efectuar el cobro al vehículo que se va a retirar de parqueadero. Para poder cobrar por el tiempo de estadía en el parqueadero se debe tener en cuenta la fecha y hora de entrada y salida del vehículo, al igual que el tipo de vehículo, pues si es moto el valor de la hora es 600 mientras que si es carro es de 1200. Es importante tener en cuenta que si al calcular la diferencia en horas y minutos entre las dos fechas, la cantidad de minutos es inferior a 6 minutos no se le cobrará una hora más, de lo contrario sí. Ejemplo, si son 5 horas y 10 minutos, se deberán cobrar 6 horas, pero si son 4 horas y 3 minutos se cobrarán solo cuatro horas.
ENTRADAS placa RESULTADOS El valor a pagar
NOMBRE RESUMEN
R3 – Retirar un vehículo del parqueadero El dueño del vehículo da la placa del vehículo y el sistema debe buscarlo para poder liberar el espacio
ENTRADAS La placa, la fecha y hora de salida RESULTADOS El vehículo ha liberado el espacio dentro del parqueadero
b) El modelo del mundo del problema Las actividades que se deben realizar para construir el modelo del mundo son: Identificar las entidades o clases.
ENTIDAD DEL MUNDO Parqueadero Puesto Reservación Fecha Vehículo
DESCRIPCIÓN Es la entidad más importante del mundo del problema. Es un atributo del Parqueadero Es un atributo del Puesto Es un atributo de la Reservación Es un atributo de la Reservación
119
Identificar las relaciones entre las clases del mundo
120
En la clase Fecha se crearon dos métodos constructores. El primero de ellos sin parámetros. El objetivo de este constructor es crer una nueva fecha con el día y hora de hoy. public Fecha() { // Se usa un calendario Gregoriano inicializado en el día de hoy GregorianCalendar gc = new GregorianCalendar( ); // Se sacan los valores de día, mes y año del calendario dia = gc.get( Calendar.DAY_OF_MONTH ); mes = gc.get( Calendar.MONTH ) + 1; anio = gc.get( Calendar.YEAR ); hora=gc.get( Calendar.HOUR ); minuto=gc.get( Calendar.MINUTE ); } El segundo constructor permite crear una fecha con los datos proporcionados por el usuario. public Fecha(int dia, int mes, int anio, int hora, int minuto) { this.dia = dia; this.mes = mes; this.anio = anio; this.hora = hora; this.minuto = minuto; } Otro método que se requiere es el método calcularDiferenciaEnMinutos(Fecha miFechaMayor). Este método le resta a una fecha la fecha que recibe por parámetro y devuelve la cantidad de horas y minutos que hay entre ambas fechas. public Fecha calcularDiferenciaEnMinutos(Fecha miFechaMayor) { GregorianCalendar menor=devolverGregorianCalendar(this); GregorianCalendar mayor=devolverGregorianCalendar(miFechaMayor); long diferencia = mayor.getTime().getTime()-menor.getTime().getTime(); double minutos = diferencia / (1000 * 60); int horas = (int) (minutos / 60); int minuto = (int) (minutos%60); // int segundos = (int) diferencia % 1000; int dias = horas/24; return new Fecha(0,0,0,horas,minuto); } Por otra parte, en la clase Reservacion se declararon los siguientes atributos y constantes: //Atributos private Vehiculo miVehiculo; private Fecha miFechaEntrada, miFechaSalida; private double valorAPagar; //Constantes public static double VALOR_CARRO=1200; public static double VALOR_MOTO=600;
121
En esta clase se require de un método constructor que permite inicializar los atributos miVehiculo y miFechaEntrada. public Reservacion( Vehiculo miVehiculo, Fecha miFechaEntrada) { this.miVehiculo = miVehiculo; this.miFechaEntrada = miFechaEntrada; } El método calcularValorAPagar() permite calcular el valor a pagar por la estadía en el parqueadero. Este método no requiere de parámetros public double calcularValorAPagar() { Fecha miF= miFechaEntrada.calcularDiferenciaEnMinutos(miFechaSalida); if(miF.getMinuto()>5) {return miF.getHora()+1;} else {return miF.getHora();} }
En la clase Puesto se ha declarado un arreglo de reservaciones. A través de este arreglo es posible saber qué vehículos se han ubicado en un determinado puesto. Cuando un nuevo vehículo llega al parqueadero y se le asigna un puesto, entonces se genera una reservación. El método agregarReservación tiene como parámetros los datos del vehículo y la fecha y hora de ingreso.
public boolean agregarReservacion(String placa,int modelo,int dia, int mes, int anio, int hora, int minuto) { Reservacion nueva=new Reservacion(new Vehiculo(placa, modelo),new Fecha(dia,mes,anio,hora,minuto)); if(contadorReservaciones<200) { misReservaciones[contadorReservaciones]=nueva; contadorReservaciones++; estado=ESTADO_OCUPADO; return true; } return false; }
Como se dijo en el caso de estudio anterior, cuando se crea un arreglo de referencias a objetos no es suficiente con reservarle memoria a la estructura contenedora. Se necesita también reservarle memoria a cada uno de los elementos. Para el caso de estudio del Parqueadero se necesita un arreglo de Puestos. A este arreglo se le debe reservar memoria, pero también a cada uno de los
122
puestos que lo componen. El método constructor de la clase Parqueadero es el encargado de cumplir este objetivo.
public Parqueadero () { // Aquí se le reserva memoria al arreglo de puestos misPuestos=new Puesto[MAXIMO]; //Este for permite reservarle memoria a cada uno de los puestos. A cada uno de ellos se le asigna un número, un estado y un tipo. for(int i=0; i<MAXIMO; i++) { misPuestos[i]=new Puesto(); misPuestos[i].setNumero(i+i); misPuestos[i].setEstado(Puesto.ESTADO_LIBRE); if(i>11) {misPuestos[i].setTipo(Puesto.PARTICULAR);} else {misPuestos[i].setTipo(Puesto.MOTO);} } }
El método para buscar un vehículo tiene como parámetro la placa. Se recorre el arreglo y si algún vehículo tiene la misma placa se devuelve true. public boolean buscarVehiculo(String placa) { for(int i=0; i<MAXIMO; i++) { if(misPuestos[i].getContadorReservaciones()>=1&& misPuestos[i].getMisReservaciones()[misPuestos[i].getContadorReservacione s()-1].getMiVehiculo().getPlaca().equals(placa)&& misPuestos[i].getEstado()==Puesto.ESTADO_OCUPADO) { return true;} }//Cierra el for return false; }
El método ubicarVehículo permite asignarle un puesto a un vehículo. Para ello se deben ingresar los datos del vehículo y la fecha y hora de ingreso. Dependiendo el tipo de vehículo se define a partir de donde iniciar a buscar espacios libres. Es de anotar, que los 12 primeros puestos están destinados a motos, es decir, tipo 1 y los restantes a carros. Se retorna el número del puesto donde quedará ubicado el vehículo. Si no se encuentran puestos libres se devuelve -1.
public int ubicarVehiculo(String placa, int modelo, int tipo, int dia, int mes, int anio, int hora, int minuto) 123
{ int inicio=0, finaliza=12; if(buscarVehiculo(placa)==false) { if(tipo==Puesto.PARTICULAR) {inicio=12; finaliza=30;} for(int i=inicio; i< finaliza;i++) { if(misPuestos[i].getEstado()==Puesto.ESTADO_LIBRE) { misPuestos[i].agregarReservacion(placa, modelo, dia, mes, anio, hora, minuto); return i; } } } return -1; }
Para finalizar se requiere de un método para liberar un espacio e indicarle al usuario el valor que debe pagar. Este método recibe la placa del vehículo y la fecha y hora de salida. public ResultadoLiberacion liberarEspacio(String placa, int dia, int mes, int anio, int hora, int minuto) { double valor=0, precio=1200; for(int i=0; i<MAXIMO; i++) { //Se identifica cuál es el puesto donde está ubicado el vehículo if(misPuestos[i].getContadorReservaciones()>=1&&misPuestos[i].getMisReser vaciones()[misPuestos[i].getContadorReservaciones()1].getMiVehiculo().getPlaca().equals(placa)&&misPuestos[i].getEstado()==P uesto.ESTADO_OCUPADO) { //Se fija la fecha de salida misPuestos[i].getMisReservaciones()[misPuestos[i].getContadorReservacione s()-1].setMiFechaSalida(new Fecha(dia, mes, anio, hora, minuto)); //Se libera el puesto misPuestos[i].setEstado(Puesto.ESTADO_LIBRE); //Se determina el valor a cobrar dependiendo del tipo if(misPuestos[i].getTipo()==Puesto.MOTO) { precio=600; } valor= misPuestos[i].getMisReservaciones()[misPuestos[i].getContadorReservacione s()-1].calcularValorAPagar()*precio; return new ResultadoLiberacion(valor, i); } } return null; }
124
3.4. Hoja de trabajo 2 Unidad III: Sala de computadores Se requiere administrar la información de una sala de cómputo. En la sala hay 20 computadores. Cada computador tiene un número asociado (de 1 a 20), un tamaño en disco duro, una cantidad de memoria Ram y un propietario. Un propietario tiene un código y un nombre. La aplicación debe permitir ingresar o en su defecto actualizar la información de cada equipo Adicionalmente debe informar el número del equipo con más disco duro Generar un listado con los números de los equipos a los cuales no se les ha fijado propietario.
3.4.1.
Comprensión del problema
a) Requisitos funcionales NOMBRE RESUMEN ENTRADAS
R1 – Informar el número del equipo con más disco duro
RESULTADOS
125
NOMBRE
R2 – Generar un listado con los números de los equipos a los cuales no se les ha
fijado propietario
RESUMEN ENTRADAS RESULTADOS
NOMBRE
R3 – Actualizar la información de un equipo
RESUMEN ENTRADAS RESULTADOS
b) El modelo del mundo del problema Algunas de las actividades que se deben realizar para construir el modelo del mundo son: Identificar las entidades o clases.
ENTIDAD DEL MUNDO Sala Computador Responsable
DESCRIPCIÓN
Identificar las relaciones entre las clases del mundo
126
En la clase Sala se encuentran los siguientes métodos: - El método constructor permite reservarle memoria al arreglo de computadores y también a cada uno de los computadores. A cada computador se le asigna de una vez el número consecutivo. public Sala() { /*MAXIMO_COMPUTADORES es una constante que indica el número máximo de computadores*/
} El método asignarCaracteristicas permite actualizar los datos de un equipo. Para ello se proporciona el número del equipo, además de la capacidad en ram y disco. public void asignarCaracteristicas( int posicion, int ram, int disco) { misComputadores[posicion].setDisco(disco); 127
misComputadores[posicion].setRam(ram); } El método asignarCaracteristicas permite actualizar la información del propietario de un equipo. public boolean asignarCaracteristicas( int posicion, String codigo, String nombre) { if(contarPropietario(codigo)<3) { misComputadores[posicion].setMiResponsable(codigo, nombre); return true; } else return false; }
El método contarPropietario recibe el código del propietario y recorre el arreglo de computadores para buscar dicho propietario. En caso de que lo encuentre incrementa el contador. public int contarPropietario(String codigo) {int contador=0;
}
El método obtenerComputadorMasDisco()no tiene parámetros. En su interior se declaran dos variables: mayor y posición. La primera de ellas mantiene constantemente actualizada con el valor del computador (capacidad del disco) que tiene más disco duro. La segunda, almacena la posición dentro del arreglo donde está ubicado este mismo computador. public int obtenerComputadorMasDisco() { int mayor=0; int posicion=0;
}
El método listarComputadoresSinPropietario() recorre el arreglo de computadores preguntando, por cada computador, si tiene propietario. public String[] listarComputadoresSinPropietario() 128
{ String arreglo[]=new String[20];
}
129
130
BIBLIOGRAFIA
Arboleda Cobo, Liliana María.Programación en red con java. Cali, Universidad ICESI, 2004
Bishop, Judy. Java Fundamentos de programación. Addison-Wesley. Segunda Edición. Madrid. 1999. ISBN: 84-7829-022-2.
Booch. Object Oriented Analysis & Design With Applications. Prentice Hall, 1998
Booch. UML El Lenguaje Unificado de Modelado. Addison Wesley
Ceballos Sierra, Francisco Javier. Java 2: curso de programación. Alfaomega, 2006. México
Dejalón G. Javier y Rodríguez J. Ignacio, Aitor, Imaz. Aprenda Java como si estuviera en primero. Escuela Superior de Ingenieros Industriales. San Sebastian. Enero 2000.
Deitel, H. Deitel P. Como programar en Java, Prentice Hall. Primera edición. México, 1994 ISBN: 970-17-0044-9.
Eckel, Bruce. Piensa en Java. Prentice-Hall, Pearson Educación. Segunda edicion. Madrid, 2003. ISBN: 84-205-3192-8.
Eriksson, H. UML 2 Toolkit. Indianapolis: Wiley 2004
Goodrich, Michael y Tamassia, Roberto. Estructuras de datos y algoritmos en Java. CECSA. Segunda edición. 2002
Hurtado Gil, Sandra Victoria. Conceptos Avanzados de Programación con JAVA. Universidad ICESI, 2002
Lee, Richard. Practical Object Oriented Development with UML and Java. Prentice-hall, 2002.
Lemay, Laura. Cadenhead Rogers. Aprendiendo java en 21 días. Prentice Hall. ISBN: 970-17-0229-8. Mexico.1999.
Oneil, Joseph. Teach Yourself JAVA. McGraw - Hill. California USA, 1999. ISBN: 0-07882570-9. 131
Richardson. Professional Java JDK 6. Wrox, 2007
Schildt, Herbert. Fundamentos de programación en Java2. Mc Graw-Hill. ISBN: 958-410228-1.
Villalobos, Jorge. Introduccion a las Estructuras de Datos. Prentice Hall, 2008
Villalobos S. Jorge A. Casallas Rubby. Fundamentos de programación - Aprendizaje Activo Basado en casos. Prentice Hall. ISBN: 970-26-0846-5. 2006
Zhang, Computer Graphics Using Java 2d & 3d,-Pearson, Enero de 2007.
132