Foros aprenderaprogramar.com

Aprender a programar => Aprender a programar desde cero => Mensaje iniciado por: Amateu en 07 de Abril 2016, 12:29

Título: Java plantear código de un método de dos formas que sean equivalentes CU00642B
Publicado por: Amateu en 07 de Abril 2016, 12:29
Después de llegar hasta este punto sin molestar en este aprendizaje paso el ejercicio que he intentado resolver. Ejercicio CU00642B del curso básico de programación Java.

Clase Casa
Código: [Seleccionar]
/**
 * Ejercicio CU00642B
 * 3/3 clases que corresponden al ejercicio
 * Es la clase que utilizará las clases SalonCasa y CocinaCasa
 * @author Amateu
 * @version 1
 */
public class Casa
{
    // Definición de vbles
    private double superficie;
    private String direccion;
    private SalonCasa salonCasa;
    private CocinaCasa cocina;

    /**
     * Constructor para inicializar las vbles por defecto
     */
    public Casa()
    {
        // initialise instance variables
        superficie = 0.0;
        direccion = "";
        salonCasa = new SalonCasa();
        cocina = new CocinaCasa();
    }

    /**
     * Constructor inicializador introduciendo parámetros
     */
    public Casa(double valorSuperficie, String valorDireccion, SalonCasa valorSalonCasa,
        CocinaCasa valorCocina)
    {
        superficie = valorSuperficie;
        direccion = valorDireccion;
        salonCasa = valorSalonCasa;
        cocina = valorCocina;
    }//Cierre del constructor

    /**
     * Métodos para establecer los atributos
     */
    public void setSuperficie (double valorSuperficie)
    {
        superficie = valorSuperficie;
    }
    public void setDireccion (String valorDireccion)
    {
        direccion = valorDireccion;
    }
    public void setSalonCasa (SalonCasa valorSalonCasa)
    {
            salonCasa = valorSalonCasa;
    }

    public void setCocinaCasa (CocinaCasa valorCocinaCasa)
    {
        cocina = valorCocinaCasa;
    }
    //Métodos para leer atributos
   
    public double getSuperficie () { return superficie; }
    public String getDireccion () { return direccion; }
    public SalonCasa getSalonCasa () { return salonCasa; }
    public CocinaCasa getCocinaCasa () { return cocina;}
}

Clase SalonCasa
Código: [Seleccionar]
/**
 * Ejercicio CU00642B
 * 1/3 clases que corresponden al ejercicio
 * @author Amateu
 * @version 1
 */
public class SalonCasa
{
    // Definición de vbles
    private int numeroDeTelevisores;
    private String tipoSalon;

    /**
     * Constructor
     * Inicializando las vbles por defecto
     */
    public SalonCasa()
    {
        // initialise instance variables
        numeroDeTelevisores = 0;
        tipoSalon = "desconocido";
    }
    /**
     * Constructor inicializador introduciendo parámetros
     */
    public SalonCasa(int valorNumeroDeTelevisores, String valorTipoSalon)
    {
        numeroDeTelevisores = valorNumeroDeTelevisores;
        tipoSalon = valorTipoSalon;
    }//Cierre del constructor

    /**
     * Métodos para establecer los atributos
     */
    public void setNumeroDeTelevisores (int valorNumeroDeTelevisores)
    {
        numeroDeTelevisores = valorNumeroDeTelevisores;
    }
    public void setTipoSalon (String valorTipoSalon)
    {
        tipoSalon = valorTipoSalon;
    }
    //Métodos para leer atributos
   
    public int getNumeroDeTelevisores () { return numeroDeTelevisores; }
    public String getTipoSalon () { return tipoSalon; }
   
}

Clase CocinaCasa
Código: [Seleccionar]
/**
 * Ejercicio CU00642B
 * 2/3 clases que corresponden al ejercicio
 * @author Amateu
 * @version 1
 */
public class CocinaCasa
{
    // Definición de vbles
    private boolean esIndependiente;
    private int numeroDeFuegos;

    /**
     * Constructor
     * Inicializando las vbles por defecto
     */
    public CocinaCasa()
    {
        // initialise instance variables
        esIndependiente = false;
        numeroDeFuegos = 0;
    }
    /**
     * Constructor inicializador introduciendo parámetros
     */
    public CocinaCasa(boolean valorEsIndependiente, int valorNumeroDeFuegos)
    {
        esIndependiente = valorEsIndependiente;
        numeroDeFuegos = valorNumeroDeFuegos;
    }//Cierre del constructor

    /**
     * Métodos para establecer los atributos
     */
    public void setEsIndependiente (boolean valorEsIndependiente)
    {
        esIndependiente = valorEsIndependiente;
    }
    public void setNumeroDeFuegos (int valorNumeroDeFuegos)
    {
        numeroDeFuegos = valorNumeroDeFuegos;
    }
    //Métodos para leer atributos
   
    public boolean getEsIndependiente () { return esIndependiente; }
    public int getNumeroDeFuegos () { return numeroDeFuegos; }
}

Gracias de antemano
Título: Re:CU00642B Ejercicio
Publicado por: RaGa en 10 de Abril 2016, 15:36
Hola Amateu:

Veo que es tu primer mensaje en el foro así que Bienvenido!
Estuve revisando tu ejercicio, y lo veo perfecto!

Como un agregado extra -ya que todo ha estado correctísimo- me gustaría plantearte lo siguiente a modo de "darle una vuelta más de tuerca al tema"...

Tú habías planteado en la clase Casa, el siguiente método:
Código: [Seleccionar]
public void setSalonCasa (SalonCasa valorSalonCasa)
    {
            salonCasa = valorSalonCasa;
    }

Está perfecto como está codificado, hace lo que que debe hacer.
Sin embargo quisiera mostrarte una alternativa distinta de codificación de este método:
Código: [Seleccionar]
    public void setSalonCasa(SalonCasa valorSalonCasa) {
        salonCasa.setNumeroDeTelevisores(valorSalonCasa.getNumeroDeTelevisores());
        salonCasa.setTipoSalon(valorSalonCasa.getTipoSalon());
    }

Esta forma de codificar el método setSalonCasa también realiza lo que se pide en el ejercicio.

Nos podríamos plantear la siguiente pregunta ¿ambas formas son equivalentes? ¿es indistinto codificar de una manera o de otra?... tomémonos un tiempo para pensarlo y analizarlo.

La respuesta es  que si bien ambas formas de codificación resuelven en nuestro caso particular el ejercicio que se plantea en la lección, hay diferencia entre una y otra forma.

Fíjate en lo siguiente: de la manera en que lo planteaste tu, lo que hacemos es asignarle al campo salonCasa, la referencia del objeto valorSalonCasa. Por lo tanto si se realizara cualquiera modificación al objeto valorSalonCasa, esas modificaciones se verían reflejadas cuando consultemos el objeto salonCasa (y viceversa) ¿ por qué? porque salonCasa apunta a valorSalonCasa, eso es lo que realiza la asignación: una asignación de referencias.

Ahora bien, si analizamos la segunda forma de codificar, vemos que el método lo que hace es asignar a los campos del objeto salonCasa, los valores de los campos del objeto valorSalonCasa. Pero ambos objetos siguen siendo independientes. Tanto salonCasa como valorSalonCasa referencian lugares de memorias distintos.

Todo lo dicho es aplicable también al método método setCocina.

Analízalo, y cualquier consulta estamos aqui para reveerlo.
Título: Re:CU00642B Ejercicio
Publicado por: Amateu en 11 de Abril 2016, 09:39
He probado modificar el método así:
Código: [Seleccionar]

       public void setSalonCasa(SalonCasa valorSalonCasa)
    {
        salonCasa.numeroDeTelevisores = valorSalonCasa.numeroDeTelevisores;
        salonCasa.tipoSalon = valorSalonCasa.tipoSalon;
    }
pensando que resultaría igual que como lo había puesto yo en un principio, vinculando los atributos. Pero comprobando su ejecución veo que coge el valor, no referencia el atributo.

¿Qué diferencia hay con utilizar los métodos de set y get?
Bueno, he tenido que cambiar de private a public la definición de variables en la clase SalonCasa. ¿Es sólo esa la diferencia?

Y donde quería llegar yo: ¿Y si quisiera que uno de los atributos de salonCasa estuviese vinculado a valorSalonCasa y el otro no?
Título: Re:CU00642B Ejercicio
Publicado por: RaGa en 11 de Abril 2016, 14:49
Hola Amateu:

Insisto en lo siguiente: tal como lo habías codificado tu estaba perfectamente resuelto, no se debía cambiar nada.
Siemplemente hicimos un agregado a la lección con la segunda opción que yo te planteaba, a modo de alternativa a la solución del ejercicio. También te explicaba "las diferencias sutiles" entra ambas posibilidades.
La elección entre adoptar una u otra solución en el futuro dependerá de problema a resolver en sí, pero en este caso en particular (CU00642B) era indistinto, ambos códigos funcionaban correctamente.

Esta otra forma de en que planteas en tu último hilo sí ya no es correcta, violamos el principio de encapsulación, lo que significa que accedemos a los campos de instancia de un objeto de forma directa. Por regla general el acceso a los campos de instancia de un objeto no deberían ser 'public'.
Siempre que querramos leer o setear un campo de instancia de un objeto será a través de sus métodos set y get, nunca de manera directa.
En principio todos los campo de instancia de un objeto deberían ser de acceso 'private'.