4. Nuevos Elementos de Modelado

4.1. Tipos Simples de Datos

En esta sección presentamos dos nuevos tipos simples de datos (boolean y char) y volvemos a estudiar algunos aspectos de los tipos introducidos en el capítulo anterior.

Comenzamos con el tipo double. Para facilitar el modelado de las características que toman valores reales, la mayoría de los lenguajes de programación proveen un tipo simple denominado double. En el caso de estudio de la tienda usaremos un atributo de este tipo para modelar el precio de cada producto. Esto nos va a permitir tener un producto cuyo precio sea, por ejemplo, $23,12 (23 pesos y 12 centavos).

Se denomina literal de un tipo de datos a un valor constante de dicho tipo. En la siguiente tabla se dan algunos ejemplos de la manera de escribir literales para los tipos de datos estudiados. A medida que vayamos viendo nuevos tipos, iremos introduciendo la sintaxis que utilizan.

Tipo en Java Ejemplo de literales Comentarios
entero (int) 564564, 12-12 Los literales de tipo entero se expresan como una secuencia de dígitos. Si el valor es negativo, dicha secuencia va precedida del símbolo "-".
real (double) 564.78564.78, 98.3-98.3 Los literales de tipo real se expresan como una secuencia de dígitos. Para separar la parte entera de la parte decimal se utiliza el símbolo ".".
cadena de caracteres ( String ) "esta es una cadena"," ", "" Los literales de tipo cadena de caracteres van entre comillas dobles. Dos comillas dobles seguidas indican una cadena de caracteres vacía. Es distinta una cadena vacía que una cadena que sólo tiene un carácter de espacio en blanco.

En el ejemplo 1 se muestra la manera de declarar y manipular los atributos de tipo double usando el caso de estudio de la tienda. También se presenta la manera de convertir los valores reales a valores enteros.

Ejemplo 1

Objetivo: Repasar la manera de manejar atributos de tipo double en el lenguaje de programación Java, usando el caso de estudio de la tienda.

public class Producto
{
    private  double  valorUnitario;
}
  • Declaración del atributo valorUnitario dentro de la clase Producto, para representar el precio del producto por unidad, antes de impuestos (sin IVA).
  • Como de costumbre, el atributo lo declaramos privado, para evitar que sea manipulado desde fuera de la clase.

Las siguientes instrucciones pueden ir como parte de cualquier método de la clase Producto:

valorUnitario = 23.12;
int valorPesos = ( int ) valorUnitario;
  • Si en la variable valor valorPesos queremos tener la parte entera del precio del producto, utilizamos el operador de conversión (int). Este operador permite convertir valores reales a enteros.
  • El operador (int) incluye los paréntesis y debe ir antes del valor que se quiere convertir.
  • Si no se incluye el operador de conversión, el compilador va a señalar un error ("Type mismatch: cannot convert from double to int").
valorUnitario = valorUnitario / 1.07;

Para construir una expresión aritmética de valor real, se pueden usar los operadores de suma(+), resta (-), multiplicación (*) y división (/).

int valorPesos = 17 / 3;
  • La división entre valores enteros da un valor entero. En el caso del ejemplo, después de la asignación, la variable valorPesos tendrá el valor 5.
  • El lenguaje Java decide en cada caso (dependiendo del tipo de los operandos) si utiliza la división entera o la división real para calcular el resultado.

Un operador que se utiliza frecuentemente en problemas aritméticos es el operador módulo (%). Este operador calcula el residuo de la división entre dos valores, y se puede utilizar tanto en expresiones enteras como reales. La siguiente tabla muestra el resultado de aplicar dicho operador en varias expresiones.

Expresión Valor Comentarios
4%44 \% 4 0 El residuo de dividir 4 por 4 es cero. El resultado de este operador se puede ver como lo que "sobra" después de hacer la división entera.
14%314 \% 3 2 El resultado de la expresión es 2, puesto que al dividir 14 por 3 se obtiene como valor entero 4 y "sobran" 2.
17%317 \% 3 2 En esta expresión el valor entero es 5 ( 5 * 3 es 15 ) y "sobran" de nuevo 2.
3%173 \% 17 3 La división entera entre 3 y 17 es cero, así que "sobran" 3.
4.5%2.24.5 \% 2.2 0.1 El operador % se puede aplicar también a valores reales. En la expresión del ejemplo, 2.2. está 2 veces en 4.5 y "sobra" 0.1.

Otro tipo simple de datos que encontramos en los lenguajes de programación es el que permite representar valores lógicos (verdadero o falso). El nombre de dicho tipo es boolean. Imagine, por ejemplo, que en la tienda queremos modelar una característica de un producto que dice si es subsidiado o no por el gobierno. De esta característica sólo nos interesaría saber si es verdadera o falsa (los únicos valores posibles), para saber si hay que aplicar o no el respectivo descuento. Este tipo de características se podría modelar usando un entero y una convención sobre la manera de interpretar su valor (por ejemplo, 1 es verdadero y 2 es falso). Es tan frecuente encontrar esta situación que muchos lenguajes resolvieron convertirlo en un nuevo tipo de datos y evitar así tener que usar otros tipos para representarlo.

El tipo boolean sólo tiene dos literales: true y false. Estos son los únicos valores constantes que se le pueden asignar a los atributos o variables de dicho tipo.

Ejemplo 2

Objetivo: Mostrar la manera de manejar atributos de tipo boolean en el lenguaje de programación Java.

En este ejemplo se utiliza una extensión del caso de estudio de la tienda, para mostrar la sintaxis de declaración y el uso de los atributos de tipo boolean.

public class Producto
{
    private boolean subsidiado;
}
  • Aquí se muestra la declaración del atributo "subsidiado" dentro de la clase Producto.
  • Dicha característica no forma parte del caso de estudio y únicamente se utiliza en este ejemplo para ilustrar el uso del tipo de datos boolean.

Las siguientes instrucciones pueden ir como parte de cualquier método de la clase Producto:

subsidiado = true; 
subsidiado = false;
  • Los únicos valores que se pueden asignar a los atributos de tipo boolean son true y false. Los operadores que nos permitirán crear expresiones con este tipo de valores, los veremos más adelante.
boolean valorLogico = subsidiado;
  • Es posible tener variables de tipo boolean, a las cuales se les puede asignar cualquier valor de dicho tipo.

El último tipo simple de dato que veremos en este capítulo es el tipo char, que sirve para representar un carácter. En el ejemplo 3 se ilustra la manera de usarlo dentro del contexto del caso de estudio. Un valor de tipo char se representa internamente mediante un código numérico llamado UNICODE.

Ejemplo 3

Objetivo: Mostrar la manera de manejar atributos de tipo char en el lenguaje de programación Java, usando una extensión del caso de estudio de la tienda.

Suponga que los productos de la tienda están clasificados en tres grupos: A, B y C, según su calidad. En este ejemplo se muestra una manera de representar dicha característica usando un atributo de tipo char.

public class Producto
{
    private char calidad;
}
  • Aquí se muestra la declaración del atributo "calidad" dentro de la clase Producto. Dicha característica será representada con un carácter que puede tomar como valores 'A', 'B' o 'C'.

Las siguientes instrucciones pueden ir como parte de cualquier método de la clase Producto:

calidad  =  'A'; 
calidad  =  'B';
  • Los literales de tipo char se expresan entre comillas sencillas. En eso se diferencian de los literales de la clase String, que van entre comillas dobles.
calidad  =  67;
  • Lo que aparece en este ejemplo es poco usual: es posible asignar directamente un código UNICODE a un atributo de tipo char. El valor 67, por ejemplo, es el código interno del carácter 'C'. El código interno del carácter 'c' (minúscula) es 99. Cada carácter tiene su propio código interno, incluso los que tienen tilde (el código del carácter 'á' es 225).
char valorCaracter = calidad;
  • Es posible tener variables de tipo char, a las cuales se les puede asignar cualquier valor de dicho tipo.

4.2. Constantes para Representar Valores Inmutables

En muchos problemas encontramos algunos valores que no van a cambiar durante la ejecución del programa (inmutables). Considere el caso de la tienda, en el que el valor del precio final del producto depende de los impuestos definidos por la ley. Según lo que vimos en el nivel anterior, cada vez que necesitemos el valor del IVA de los productos de papelería, debemos escribir su valor numérico (0.16). Para facilitar la lectura y escritura del código, los lenguajes de programación permiten asociar un nombre significativo al valor, para así reemplazar el valor numérico dentro del código. Estos nombres asociados se denominan constantes.

Estas constantes pueden ser de cualquier tipo de datos (por ejemplo, puede haber una constante de tipo String o double) y se les debe fijar su valor desde la declaración. Dicho valor no puede ser modificado en ningún punto del programa.

El ejemplo 4 desarrolla esa idea con el caso de la tienda y muestra la sintaxis en Java para declarar y usar constantes.

Ejemplo 4

Objetivo: Mostrar el uso de constantes para representar los valores inmutables, usando el caso de estudio de la tienda.

En este ejemplo ilustramos el uso de constantes para representar los posibles valores del IVA de los productos.

public class Producto
{
    //--------------------------------------
    // Constantes
    //--------------------------------------

    private final static double IVA_PAPELERIA = 0.16;
    private final static double IVA_SUPERMERCADO = 0.04;
    private final static double IVA_FARMACIA = 0.12;
    ...
}
  • Declaramos tres constantes que tienen los valores posibles del IVA en el problema: 16%, 12% y 4%. Estas constantes se llaman IVA_FARMACIA, IVA_PAPELERIA e IVA_SUPERMERCADO.
  • Son constantes de tipo double, puesto que de ese tipo son los valores inmutables que queremos representar.
  • Las constantes se declaran privadas si no van a ser usadas por fuera de la clase.
  • Para inicializar una constante, se debe elegir un literal del mismo tipo de la constante, o una expresión.
  • Dentro de la declaración de la clase, se agrega una zona para declarar las constantes. Es conveniente situar esa zona antes de la declaración de los atributos.

Las siguientes instrucciones pueden ir como parte de cualquier método de la clase Producto:

precio = valorUnitario * ( 1 + IVA_SUPERMERCADO ); 
precio = valorUnitario * ( 1 + 0.04 );
  • Las constantes sólo sirven para reemplazar el valor que representan. Las dos instrucciones del ejemplo son equivalentes y permiten calcular el precio al consumidor, aplicándole un IVA del 4% al precio de base del producto.
  • La ventaja de las constantes es que cuando alguien lee el programa entiende a qué corresponde el valor 0.04 (puesto que también podría corresponder a los intereses o algún otro tipo de impuesto).

Esta práctica de definir constantes en sustitución de aquellos valores que no cambian durante la ejecución tiene muchas ventajas y es muy apreciada cuando hay necesidad de hacer el mantenimiento a un programa. Suponga, por ejemplo, que el gobierno autoriza un incremento en los impuestos y, ahora, el impuesto sobre los productos de supermercado pasa del 4% al 6%. Si dentro del programa siempre utilizamos la constante IVA_SUPERMERCADO para referirnos al valor del impuesto sobre los productos de supermercado, lo único que debemos hacer es reemplazar el valor 0.04 por 0.06 en la declaración de la constante. Si por el contrario, en el código del programa no utilizamos el nombre de la constante sino el valor, tendríamos que ir a buscar todos los lugares en el código donde aparece el valor 0.04 (que hace referencia al impuesto sobre los productos de supermercado) y reemplazarlo por 0.06. Si hacemos lo anterior, fácilmente podemos pasar por alto algún lugar e introducir así un error en el programa.

Por convención, las constantes siempre van en mayúsculas. Si el nombre de la constante contiene varias palabras, es usual separarlas con el carácter "_". Por ejemplo podríamos tener una constante llamada PRECIO_MAXIMO.

Imaginémonos una nueva constante en la clase producto que define el precio máximo que puede tener un producto.

public class Producto
{
    //--------------------------------------
    // Constantes
    //--------------------------------------

    public final static double PRECIO_MAXIMO = 500000.0;
}

El siguiente método podría pertenecer a la clase Tienda:

public class Tienda
{
    public double ejemplo( )
    {
        return Producto.PRECIO_MAXIMO;
    }
}
  • Por fuera de la clase Producto, las constantes pueden usarse indicando la clase en la cual fueron declaradas (siempre y cuando hayan sido declaradas como public en esa clase).

4.3. Enumeraciones para Definir el Dominio de un Atributo

Considere el caso de la tienda, en el que queremos modelar la característica de tipo de producto, el cual puede ser de tres tipos distintos: supermercado, papelería o droguería. En el nivel anterior vimos que es posible utilizar el tipo entero para representar esta característica, y asociar un número con cada uno de los valores posibles. Sin embargo, para estos casos, los lenguajes de programación permiten agrupar estos posibles valores de la característica, asignando solamente un nombre significativo para cada uno de ellos, sin asignarles ningún valor. Estas agrupaciones de valores de datos se denominan enumeraciones. De esta forma, dentro de los métodos podemos usar los nombres existentes en una enumeración.

El ejemplo 5 desarrolla esa idea con el caso de la tienda y muestra la sintaxis en Java para declarar y usar enumeraciones.

Ejemplo 5

Objetivo: Mostrar el uso de enumeraciones para representar los valores posibles de alguna característica.

Usando el caso de estudio de la tienda, en este ejemplo se muestra una manera de crear una enumeración para representar la
característica de tipo de producto.

public class Producto
{
    //--------------------------------------
    // Enumeraciones
    //--------------------------------------
    public enum Tipo
    {
        PAPELERIA,
        SUPERMERCADO,
        FARMACIA
    }       

    //--------------------------------------
    // Atributos
    //--------------------------------------
    private Tipo tipo;
    ...
}
  • Se declara una enumeración llamada Tipo, para modelar el conjunto de nombres que podrán representar un tipo de producto.
  • Dentro de la declaración del tipo, se agregan los nombres significativos de los tres tipos de producto existentes: PAPELERIA, SUPERMERCADO y FARMACIA.
  • Se declara un atributo llamado "tipo" dentro de la clase Producto, para representar esa característica. El tipo asignado a este atributo es la enumeración que creamos arriba.
  • Dentro de la declaración de la clase, se agrega una zona para declarar las constantes. Es conveniente situar esa zona antes de la declaración de los atributos.

Para poder usar una enumeración, se debe escribir el nombre de la enumeración y después llamar el valor que se desea asignar. Las siguientes instrucciones pueden ir como parte de cualquier método de la clase Producto:

tipo = Tipo.PAPELERIA; 
tipo = Tipo.SUPERMERCADO;
tipo = Tipo.FARMACIA;

Cualquiera de esas tres asignaciones define el tipo de un producto (no las tres a la vez, por supuesto). La ventaja de usar una enumeración (PAPELERIA) en lugar de un valor numérico es que el programa resultante es mucho más fácil de leer y entender.

El siguiente método podría pertenecer a la clase Tienda:

public void ejemplo( )
{
    ...
    tipoVenta = Tipo.PAPELERIA;
    tipoCompra = Tipo.SUPERMERCADO;
    ...
}
  • Por fuera de la clase Producto, las enumeraciones se llaman de la misma manera que se llamaba dentro de la clase donde fueron declaradas (siempre y cuando hayan sido declaradas como public en esa clase).
  • En el ejemplo estamos suponiendo que tipoVenta y tipoCompra son atributos de la clase Tienda.

4.4. Manejo de Asociaciones Opcionales

Supongamos que queremos modificar el enunciado del caso de la tienda, para que el programa pueda manejar 1, 2, 3 ó 4 productos. Lo primero que debemos hacer entonces es modificar el diagrama de clases, para indicar que las asociaciones pueden o no existir. Para esto usamos la sintaxis de UML que se ilustra en la figura 2.2, y que dice que las asociaciones son opcionales. Esta característica se denomina cardinalidad de la asociación y se verá más a fondo en el nivel 3. Por ahora podemos decir que la cardinalidad define el número de instancias de una clase que pueden manejarse a través de una asociación. En el caso de una asociación opcional, la cardinalidad es 0..1 (para expresar la cardinalidad, se usan dos números separados con dos puntos), puesto que a través de la asociación puede manejarse un objeto de la otra clase o ningún objeto.

Fig. 2.2 Diagrama de clases con asociaciones opcionales
  • La cardinalidad de la asociación llamada producto1 entre la clase Tienda y la clase Producto es cero o uno (0..1), para indicar que puede o no existir el objeto que representa la asociación producto1. Lo mismo sucede con cada una de las demás asociaciones.
  • Si en el diagrama no aparece ninguna cardinalidad en una asociación, se interpreta como que ésta es 1 (existe exactamente un objeto de la otra clase).
  • En la figura 2.3 aparece un ejemplo de un diagrama de objetos para este diagrama de clases.

Dentro de un método, para indicar que el objeto correspondiente a una asociación que no está presente (que no hay, por ejemplo, un objeto de la clase Producto para la asociación producto1) se utiliza el valor especial null (producto1 = null;). En la figura 2.3 se muestra un ejemplo de un diagrama de objetos para el modelo conceptual de la figura anterior.

Cuando se intenta llamar un método a través de una asociación cuyo valor es null, el computador muestra el error: NullPointerException.

Fig. 2.3 Diagrama de objetos con asociaciones opcionales

El ejemplo anterior lo utilizamos únicamente para ilustrar la idea de una asociación opcional. En el resto del capítulo seguiremos trabajando con el caso inicial, en el cual todas las asociaciones entre la clase Tienda y la clase Producto tienen cardinalidad 1, tal como se muestra en el ejemplo 6.

Ejemplo 6

Objetivo: Mostrar las declaraciones de las clases Tienda y Producto que vamos a usar en el resto del capítulo.

En este ejemplo se muestra un diseño posible para las clases del caso de estudio de la tienda. Se presenta tanto el diagrama de clases en UML como las respectivas declaraciones en Java. En el diseño se incluyen los métodos de cada una de las clases.

El diagrama de clases consta de las clases Tienda y Producto, con 4 asociaciones entre ellos (todas de cardinalidad 1). Para cada clase se muestran los atributos que modelan las características importantes para el problema. Entre los principales atributos de la clase Producto están su nombre, su tipo, su valor unitario antes de impuestos, etc.
public class Tienda
{
    //---------------------------------
    // Atributos
    //---------------------------------
    private Producto producto1;
    private Producto producto2;
    private Producto producto3;
    private Producto producto4;
    private double dineroEnCaja;
    ...

    //-------------------------------------------
    //Métodos
    //-------------------------------------------
    public Producto darProducto1( ) { ... } 
    public Producto darProducto2( ) { ... } 
    public Producto darProducto3( ) { ... } 
    public Producto darProducto4( ) { ... }
    public double darDineroEnCaja( ) { ... }

}
  • Se modelan los 4 productos, unidos a la tienda con las asociaciones llamadas producto1, producto2, producto3 y producto4. Fíjese que las asociaciones y los atributos se declaran siguiendo la misma sintaxis. El dinero total que hay en caja de la tienda se modela con un atributo de tipo double.
  • Esta es la lista de signaturas de algunos de los métodos de la clase Tienda que utilizaremos en la siguiente sección. Esta lista se irá completando poco a poco, a medida que avancemos en el capítulo.
public class Producto
{
    //-------------------------------------------
    // Enumeraciones
    //-------------------------------------------
    /**
     * Enumeradores para los tipos de producto.
     */
    public enum Tipo
    {
        PAPELERIA,
        SUPERMERCADO,
        DROGUERIA
    }
    //-------------------------------------------
    // Constantes
    //-------------------------------------------
    private final static double IVA_PAPELERIA = 0.16;
    private final static double IVA_SUPERMERCADO = 0.04;
    private final static double IVA_DROGUERIA = 0.12;

    //-------------------------------------------
    // Atributos
    //-------------------------------------------
    private String nombre;
    private Tipo tipo;
    private double valorUnitario;
    private int cantidadBodega;
    private int cantidadMinima;
    private int cantidadUnidadesVendidas;

    //-------------------------------------------
    //Métodos
    //-------------------------------------------
    public String darNombre( ) { ... }
    public Tipo darTipo( ) { ... }
    public double darValorUnitario( ) { ... }
    public int darCantidadBodega( ) { ... }
    public int darCantidadMinima( ) { ... }
    public int darCantidadUnidadesVendidas( ) { ... }
}
  • En la clase Producto, se declaran primero las constantes para representar los valores de modelado de los atributos. Luego, las constantes que representan valores inmutables.
  • En la segunda zona va la declaración de los atributos de la clase.
  • En la tercera zona se observa la lista de signaturas de algunos de los métodos de la clase Producto que utilizaremos en la siguiente sección. Esta lista se irá completando poco a poco, a medida que avancemos en el capítulo.

results matching ""

    No results matching ""