Autor Tema: Ejercicio CU00673B palabras clave 'static' y 'final' java  (Leído 4548 veces)

toni_apr

  • Avanzado
  • ****
  • Mensajes: 497
  • Curiosidad, es uno de los pilares del Conocimiento
    • Ver Perfil
Envío 3 clases:
Clase TextCirculo con el main
Código: [Seleccionar]
/**
 * Detalles de la clase.
 * @author (Toni)
 * @version (0)
 */
public class TestCirculo {             // Atributos de la clase TestCirculo

    //Constructor para objetos de la clase TestCirculo
    public TestCirculo() {            // Inicializa atributos

    } // Fin del constructor TestCirculo

    // Siguen los setters para los atributos de la clase TestCirculo

    // Ahora los getters para los atributos de la clase TestCirculo

    // Y seguidamente, metodos varios.
    public static void main (String [] args) {
        Mensaje mensaje = new Mensaje ("\tA ver señores. ¿Quién quiere probar.? \n" +
                "\tDenme un RADIO o un DIÁMETRO, y haré filigranas.");
        boolean masCalculos = true;            // Condición del while
        String opcionRD = "";                  // opción Radio o Diámetro
        String tmpRD ="", digitosString = "";  // digitosString. Valor numérico introducido por teclado
        double valorRD = 0.0d;                 // valor del radio/diámetro
        Circulo cir = new Circulo();
        do {
            opcionRD = mensaje.responde ("\nDígame, que me da Vd. Radio o Diámetro: (R/D)",0);
            if (opcionRD.length() == 0) {      // Se ha pulsado INTRO
                mensaje.muestra ("Si no quiere hacer más pruebas. Terminamos.");
                break; // saliendo del while
            }
            opcionRD = opcionRD.substring(0,1).toUpperCase();
            if (!opcionRD.equals("R") && !opcionRD.equals("D")) {
                mensaje.muestra ("Esa opción no está disponible. Si quiere terminar, pulse INTRO directamente.");
            } else {
                if (opcionRD.equals("R")) { tmpRD = "Radio"; } else { tmpRD = "Diámetro"; }
                digitosString = numeroValido(mensaje.responde ("Introduzca su " + tmpRD + " por favor:",0));
                if (digitosString == null) {
                    mensaje.muestra ("Introduzca un valor numérico válido. Por favor, inténtelo de nuevo.");
                } else {
                    valorRD = Double.valueOf(digitosString);
                    if (opcionRD.equals("D")) { valorRD = valorRD / 2; }
                    mensaje.muestra ("El área para este círculo, es de:........ " + cir.AreaCirculo(valorRD) + " unidades cuadradas.");
                    mensaje.muestra ("La circunferencia de este círculo, es de: " + cir.LongitudCircunferencia(valorRD) + " unidades."); 
                }
            }     
        } while (masCalculos);       // fin del while
    } // fin del main
    private static String numeroValido(String cad) {
        boolean punto = false;
        char c =' ';
        cad = cad.trim();
        for (int i = 0; i < cad.length(); i++) {
            c = cad.charAt(i);
            if (c==48 || c==49 || c==50 || c==51 || c==52 || c==53 || c==54 || c==55 || c==56 || c==57) {  // solo dígitos
            } else if (c==46)  { // el punto decimal
                if ( punto ) { return null; }  // no puede haber más de un punto decimal
                punto = true;
            } else           { return null; } // ha aparecido un caracter no dígito
        }
        return cad;
    } // fin del soloDigitos
} // Fin de la clase TestCirculo
Clase Circulo, usando 'static final' (un solo espacio de memoria para el atributo en todos los objetos de la clase y valor constante que no se puede modificar)
Código: [Seleccionar]
/**
 * Detalles de la clase.
 * @author (Toni)
 * @version (0)
 */
public class Circulo {             // Atributos de la clase Circulo
    private static final double PI = 3.1416d;
    private double radio;
    //Constructor para objetos de la clase Circulo
    public Circulo() {            // Inicializa atributos
        radio = 1;
    } // Fin del constructor Circulo
    public Circulo (double radio) {
        this.radio = radio;
    }
    // Siguen los setters para los atributos de la clase Circulo
    public void setRadio (double radio)                 { this.radio = radio; }
    // Ahora los getters para los atributos de la clase Circulo
    public double getRadio ()                           { return radio; }

    // Y seguidamente, metodos varios.
    public double AreaCirculo ()                         { return (PI * radio * radio); }

    public double AreaCirculo (double radioX)            { return (PI * radioX * radioX); }

    public double LongitudCircunferencia ()              { return (2 * PI * radio); }

    public double LongitudCircunferencia (double radioX) { return (2 * PI * radioX); }
   
} // Fin de la clase Circulo
Clase Mensaje para entradas de teclado
Código: [Seleccionar]
import java.util.Scanner;
/**
 * Detalles de la clase. El método presenta mensajes por pantalla... y devuelve entradas de teclado
 * @author (Toni)
 * @version (0)
 */
public class Mensaje { // Atributos de la clase Mensaje
    private String texto;
    private int valor;
    /**
     * Mostrará el texto con salto de línea final.
     */
    public Mensaje (String frase) { //Constructor 1 parámetro para objetos de la clase Mensaje. Inicializa atributos
        texto = frase;
        valor = 1;
        muestra (texto, valor);
    }

    /**
     * Muestra el texto con salto de línea o no según param.
     * Valores param:
     * 0 = Sin salto de línea.
     * 1, u otro valor = Con salto de línea.
     */ 
    public Mensaje (String frase, int param) {
        texto = frase;
        valor = param;
        muestra (texto, valor);
    }
    // Siguen los setters para los atributos de la clase Mensaje
    public void setTexto (String texto) { this.texto = texto; }

    public void setValor (int valor)    { this.valor = valor; }
    // Ahora los getters para los atributos de la clase Mensaje
    public String getTexto ()           { return texto; }

    public int getValor ()              { return valor; }

    // Y seguidamente, procedimientos y funciones varios.
    /**
     * Mostrar el texto con salto de línea (sin segundo parámetro)
     */   
    public void muestra (String frase) {
        muestra (frase, 1);
    }// fin de muestra 1 parámetro

    /**
     * Valores param:
     * 0 = Sin salto de línea.
     * 1, u otro valor = Con salto de línea.
     */   
    public void muestra (String frase, int param) {
        texto = frase;
        valor = param;
        if (valor == 0) { System.out.print (texto + " ");
        }          else { System.out.println (texto); }
    }// fin de muestra 2 parámetros

    /**
     * Sin segundo parámetro el mensaje incluirá salto de línea. Devuelve entrada de teclado
     */
    public String responde (String frase) {
        return responde (frase, 1);
    }// fin de responde 1 parámetro

    /**
     * Valores param:
     * 0 = Sin salto de línea + entrada por teclado.
     * 1, u otro valor = Con salto de línea + entrada por teclado.
     */
    public String responde (String frase, int param) {
        texto = frase;
        valor = param;
        muestra (texto, valor);
        Scanner entradaEscaner = new Scanner(System.in);
        return entradaEscaner.nextLine();
    }// fin de responde 2 parámetros
} // Fin de la clase Mensaje
En el ejercicio se hace la siguiente pregunta:
Citar
¿Es posible crear un método en la clase Circulo para establecer el valor de numeroPi? ¿Por qué?
Respuesta: No. Porque se ha declarado con la palabra clave 'final' que quiere decir 'constante' que no se puede modificar.
« Última modificación: 31 de Agosto 2014, 18:57 por Alex Rodríguez »

Ogramar

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 2662
    • Ver Perfil
Re:Ejercicio CU00673B palabras clave 'static' y 'final'
« Respuesta #1 en: 17 de Julio 2014, 09:27 »
Hola, lo he chequeado y el programa va bien. No me parece del todo acertado en la clase Circulo tener métodos para calcular el área del círculo y la longitud de circunferencia según el valor del atributo radio del objeto y por otro lado según un parámetro recibido por otro método. Una clase debe tener cohesión: representar algo concreto, no varias cosas a la vez, por tanto en mi opinión deberías tener una clase que se basa en su atributo y no en parámetros recibidos, o al revés. Pero no una clase que mezcla ambos conceptos. Podrías tener dos clases, una Circulo (para basarse en sus atributos) y otra GestorCirculos (para recibir parámetros), así quedaría claro qué hace cada clase.

En la clase con el método main tienes un método numeroValido para comprobar si una entrada es un número válido. Desde el momento en que esto no forma parte de la gestión del flujo del programa, sería mejor tenerlo en una clase independiente que podrías llamar ComprobadorNumeroValido.

La respuesta a la pregunta es como dices si es constante no se puede modificar

Saludos!

toni_apr

  • Avanzado
  • ****
  • Mensajes: 497
  • Curiosidad, es uno de los pilares del Conocimiento
    • Ver Perfil
Re:Ejercicio CU00673B palabras clave 'static' y 'final'
« Respuesta #2 en: 17 de Julio 2014, 21:40 »
Hola Ogramar. Gracias por tus comentarios.

Entiendo como tú dices, que una clase debe representar algo concreto y no varias cosas a la vez.

He modificado la clase Circulo, ahora se llama Circulo1, donde he eliminado los métodos que recibian parámetros.
He creado una clase nueva NumeroValido y he eliminado su código de la clase del main
El main está modificado para adaptarse a los métodos de la nueva clase Circulo1 y NumeroValido.

Adjunto clases TestCirculo1 con main
Código: [Seleccionar]
/**
 * Detalles de la clase.
 * @author (Toni)
 * @version (0)
 */
public class TestCirculo1 {             // Atributos de la clase TestCirculo1

    //Constructor para objetos de la clase TestCirculo1
    public TestCirculo1() {            // Inicializa atributos

    } // Fin del constructor TestCirculo1

    // Siguen los setters para los atributos de la clase TestCirculo1

    // Ahora los getters para los atributos de la clase TestCirculo1

    // Y seguidamente, metodos varios.
    public static void main (String [] args) {
        // la siguiente línea es añadida
        NumeroValido numVal = new NumeroValido();
        Mensaje mensaje = new Mensaje ("\tA ver señores. ¿Quién quiere probar.? \n" +
                "\tDenme un RADIO o un DIÁMETRO, y haré filigranas.");
        boolean masCalculos = true;            // Condición del while
        String opcionRD = "";                  // opción Radio o Diámetro
        String tmpRD ="", digitosString = "";  // digitosString. Valor numérico introducido por teclado           
        double valorRD = 0.0d;                 // valor del radio/diámetro
        Circulo1 cir = new Circulo1();
        do {
            opcionRD = mensaje.responde ("\nDígame, que me da Vd. Radio o Diámetro: (R/D)",0);
            if (opcionRD.length() == 0) {      // Se ha pulsado INTRO
                mensaje.muestra ("Si no quiere hacer más pruebas. Terminamos.");
                break; // saliendo del while
            }
            opcionRD = opcionRD.substring(0,1).toUpperCase();
            if (!opcionRD.equals("R") && !opcionRD.equals("D")) {
                mensaje.muestra ("Esa opción no está disponible. Si quiere terminar, pulse INTRO directamente.");
            } else {
                if (opcionRD.equals("R")) { tmpRD = "Radio"; } else { tmpRD = "Diámetro"; }
                // la siguiente línea es modificada
                numVal.setEntrada(mensaje.responde ("Introduzca su " + tmpRD + " por favor:",0));
                // la siguiente línea es añadida
                digitosString = numVal.devuelve();
                // la siguiente línea ha sido sustituida, ahora se muestra como comentario
                // digitosString = numeroValido(mensaje.responde ("Introduzca su " + tmpRD + " por favor:",0));
                if (digitosString == null) {
                    mensaje.muestra ("Introduzca un valor numérico válido. Por favor, inténtelo de nuevo.");
                } else {
                    valorRD = Double.valueOf(digitosString);
                    if (opcionRD.equals("D")) { valorRD = valorRD / 2; }
                    // la siguiente línea es añadida
                    cir.setRadio(valorRD);
                    mensaje.muestra ("El área para este círculo, es de:........ " + cir.AreaCirculo() + " unidades cuadradas.");
                    mensaje.muestra ("La circunferencia de este círculo, es de: " + cir.LongitudCircunferencia() + " unidades."); 
                }
            }     
        } while (masCalculos);       // fin del while
    } // fin del main
} // Fin de la clase TestCirculo1
Clase Circulo1 modificada
Código: [Seleccionar]

/**
 * Detalles de la clase.
 * @author (Toni)
 * @version (1)
 */
public class Circulo1 {             // Atributos de la clase Circulo1
    private static final double PI = 3.1416d;
    private double radio;
    //Constructor para objetos de la clase Circulo1
    public Circulo1() {            // Inicializa atributos
        radio = 1;
    } // Fin del constructor Circulo1
    public Circulo1 (double radio) {
        this.radio = radio;
    }
    // Siguen los setters para los atributos de la clase Circulo1
    public void setRadio (double radio)                 { this.radio = radio; }
    // Ahora los getters para los atributos de la clase Circulo1
    public double getRadio ()                           { return radio; }

    // Y seguidamente, metodos varios.
    public double AreaCirculo ()                         { return (PI * radio * radio); }
    // el siguiente método ha sido eliminado
    // public double AreaCirculo (double radioX)            { return (PI * radioX * radioX); }

    public double LongitudCircunferencia ()              { return (2 * PI * radio); }
    // el siguiente método ha sido eliminado
    // public double LongitudCircunferencia (double radioX) { return (2 * PI * radioX); }

} // Fin de la clase Circulo1
Clase NumeroValido
Código: [Seleccionar]
package libToni.mensa;
/**
 * Detalles de la clase.
 * @author (Toni)
 * @version (0)
 */
public class NumeroValido {             // Atributos de la clase NumeroValido
    String entrada;
    //Constructor para objetos de la clase NumeroValido
    public NumeroValido() {            // Inicializa atributos
        entrada = "0";
    } // Fin del constructor NumeroValido
   
    public NumeroValido(String entrada) {
        this.entrada = entrada;
    }
   
    // Siguen los setters para los atributos de la clase NumeroValido
    public void setEntrada (String entrada) { this.entrada = entrada; }
    // Ahora los getters para los atributos de la clase NumeroValido
    public String getEntrada () { return entrada; }
    // Y seguidamente, metodos varios.
    public String devuelve (String valorEntrada) {
        setEntrada (valorEntrada);
        return devuelve ();
    }
   
    public String devuelve () {
        boolean punto = false;
        char c =' ';
        entrada = entrada.trim();
        for (int i = 0; i < entrada.length(); i++) {
            c = entrada.charAt(i);
            if (c==48 || c==49 || c==50 || c==51 || c==52 || c==53 || c==54 || c==55 || c==56 || c==57) {  // solo dígitos
            } else if (c==46)  { // el punto decimal
                if ( punto ) { return null; }  // no puede haber más de un punto decimal
                punto = true;
            } else           { return null; } // ha aparecido un caracter no dígito
        }
        return entrada;
    }
} // Fin de la clase NumeroValido
Clase Mensaje
Código: [Seleccionar]
import java.util.Scanner;
/**
 * Detalles de la clase. El método presenta mensajes por pantalla... y devuelve entradas de teclado
 * @author (Toni)
 * @version (0)
 */
public class Mensaje { // Atributos de la clase Mensaje
    private String texto;
    private int valor;
    /**
     * Mostrará el texto con salto de línea final.
     */
    public Mensaje (String frase) { //Constructor 1 parámetro para objetos de la clase Mensaje. Inicializa atributos
        texto = frase;
        valor = 1;
        muestra (texto, valor);
    }

    /**
     * Muestra el texto con salto de línea o no según param.
     * Valores param:
     * 0 = Sin salto de línea.
     * 1, u otro valor = Con salto de línea.
     */ 
    public Mensaje (String frase, int param) {
        texto = frase;
        valor = param;
        muestra (texto, valor);
    }
    // Siguen los setters para los atributos de la clase Mensaje
    public void setTexto (String texto) { this.texto = texto; }

    public void setValor (int valor)    { this.valor = valor; }
    // Ahora los getters para los atributos de la clase Mensaje
    public String getTexto ()           { return texto; }

    public int getValor ()              { return valor; }

    // Y seguidamente, procedimientos y funciones varios.
    /**
     * Mostrar el texto con salto de línea (sin segundo parámetro)
     */   
    public void muestra (String frase) {
        muestra (frase, 1);
    }// fin de muestra 1 parámetro

    /**
     * Valores param:
     * 0 = Sin salto de línea.
     * 1, u otro valor = Con salto de línea.
     */   
    public void muestra (String frase, int param) {
        texto = frase;
        valor = param;
        if (valor == 0) { System.out.print (texto + " ");
        }          else { System.out.println (texto); }
    }// fin de muestra 2 parámetros

    /**
     * Sin segundo parámetro el mensaje incluirá salto de línea. Devuelve entrada de teclado
     */
    public String responde (String frase) {
        return responde (frase, 1);
    }// fin de responde 1 parámetro

    /**
     * Valores param:
     * 0 = Sin salto de línea + entrada por teclado.
     * 1, u otro valor = Con salto de línea + entrada por teclado.
     */
    public String responde (String frase, int param) {
        texto = frase;
        valor = param;
        muestra (texto, valor);
        Scanner entradaEscaner = new Scanner(System.in);
        return entradaEscaner.nextLine();
    }// fin de responde 2 parámetros
} // Fin de la clase Mensaje
Ogramar, quiero pedirte tu opinión sobre lo siguiente.
En la clase NumeroValido he incluido un método (verás que soy insistente)
Citar
public String devuelve (String valorEntrada) {
        setEntrada (valorEntrada);
        return devuelve ();
    }
que recibe como parámetro el String del que quiero saber si es un valor numérico válido.
Verás que este método hace dos cosas, 1º invoca al setter 'setEntrada' con el parámetro recibido, y luego 2º llama al método estandard de la clase
Citar
public String devuelve () {
...
}
para tomar las decisiones de propias de la clase.

Mi pregunta es la siguiente: ¿La existencia de este método desvirtúa la 'concreción' de la clase?
Por mi parte me resulta muy cómodo llamar al método con parámetro que hacer dos llamadas, una para establecer el atributo y otra para obtener el resultado.

Gracias, espero tus observaciones.

Ogramar

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 2662
    • Ver Perfil
Re:Ejercicio CU00673B palabras clave 'static' y 'final'
« Respuesta #3 en: 18 de Julio 2014, 10:05 »
Hola, viendo los cambios:

Reorganización del código y las clases: bien.

Nombres de las clases: intenta mejorarlos, por ejemplo NumeroValido no dice tanto sobre lo que hace la clase como ValidadorNumero (indica que la clase valida) o ComprobadorNumero (indica que la clase comprueba).

Sobre la pregunta: ¿La existencia de este método desvirtúa la 'concreción' de la clase?

Este método no mantiene cohesión: está haciendo al mismo tiempo el trabajo de un método set y otro proceso. Un método no debe mezclar cosas. Creo que donde estás fallando es en pensar que una clase siempre tiene que tener atributos y trabajar en base a sus atributos. En esta clase, que podríamos llamar ValidadorNumero, no tienes por qué usar atributos. La tarea de la clase va a ser recibir un número (desde fuera), realizar ciertas operaciones con ese número y devolver un resultado. Por tanto te basta con recibir la información desde fuera, no necesitas atributos. No todas las clases han de tener atributos. Aunque normalmente una clase tiene atributos y métodos, algunas clases son para operar con información que reciben desde fuera y pueden carecer de atributos. Es más lógico eliminar el atributo, eliminar los constructores, eliminar los getters y setters y dejar únicamente el método devuelve (que tampoco es un buen nombre, sería mejor comprobarNumero por ejemplo. El método devuelve trabajaría recibiendo un parámetro y con ese parámetro trabaja, no tiene por qué trabajar con un atributo de la clase.

Saludos!

toni_apr

  • Avanzado
  • ****
  • Mensajes: 497
  • Curiosidad, es uno de los pilares del Conocimiento
    • Ver Perfil
Re:Ejercicio CU00673B palabras clave 'static' y 'final'
« Respuesta #4 en: 18 de Julio 2014, 22:23 »
Hola Ogramar.
Si, eso es lo que me pasa.
No se porque, creía que una clase debe tener siempre atributos, que formaba parte de la filosofía de una clase.
Así ya me gusta más. Hasta ahora me encorsetaba arrastrando unos atributos arriba y abajo.

Lo de escoger nombres más adecuados. También he de mejorarlo.

Tus comentarios me han ilustrado. Gracias. :)

 

Sobre la educación, sólo puedo decir que es el tema más importante en el que nosotros, como pueblo, debemos involucrarnos.

Abraham Lincoln (1808-1865) Presidente estadounidense.

aprenderaprogramar.com: Desde 2006 comprometidos con la didáctica y divulgación de la programación

Preguntas y respuestas

¿Cómo establecer o cambiar la imagen asociada (avatar) de usuario?
  1. Inicia sesión con tu nombre de usuario y contraseña.
  2. Pulsa en perfil --> perfil del foro
  3. Elige la imagen personalizada que quieras usar. Puedes escogerla de una galería de imágenes o subirla desde tu ordenador.
  4. En la parte final de la página pulsa el botón "cambiar perfil".