Foros aprenderaprogramar.com

Aprender a programar => C, C++, C#, Java, Visual Basic, HTML, PHP, CSS, Javascript, Ajax, Joomla, MySql y más => Mensaje iniciado por: Dimitar Stefanov en 01 de Marzo 2016, 10:34

Título: Java Por qué no funciona una clase si quito constructor en otra clase CU00642B
Publicado por: Dimitar Stefanov en 01 de Marzo 2016, 10:34
Buenas a toda la comunidad de programadores:)

Aquí pongo la solución del ejercicio CU00642B del curso Java desde cero.

Citar
EJERCICIO

Define tres clases: Casa, SalonCasa y CocinaCasa. La clase SalonCasa debe tener como atributos numeroDeTelevisores (int) y tipoSalon (String) y disponer de un constructor que los inicialice a 0 y “desconocido”. La clase CocinaCasa debe tener como atributos esIndependiente (boolean) y numeroDeFuegos (int) y un constructor que los inicialice a false y 0. La clase Casa tendrá los siguientes atributos de clase: superficie (double), direccion (String), salonCasa (tipo SalonCasa) y cocina (tipo CocinaCasa). Define un constructor para la clase Casa que establezca a unos valores de defecto los atributos simples y que cree nuevos objetos si se trata de atributos objeto. Define otro constructor que reciba como parámetros la superficie, dirección y un objeto de tipo SalonCasa y otro de tipo CocinaCasa. Compila el código para comprobar que no presenta errores, y crea un objeto de tipo Casa usando el constructor que recibe parámetros. Ten en cuenta que antes tendrás que haber creado los objetos de tipo SalonCasa y CocinaCasa para poder pasárselos al constructor. Comprueba que el objeto Casa se inicializa correctamente consultando el valor de sus atributos después de haber creado el objeto.

Código del objeto (clase) salón casa:

Código: [Seleccionar]
public class SalonCasa{
    private int numeroDeTelevisores;
    private String tipoSalon;
   
    public SalonCasa(){
        numeroDeTelevisores = 0;
        tipoSalon = "desconocido";
    }
   
    public SalonCasa(int valorNumeroDeTelevisores, String valorTipoSalon){
        numeroDeTelevisores = valorNumeroDeTelevisores;
        tipoSalon = valorTipoSalon;
    }
   
    public void setNumeroDeTelevisores(int valorNumeroDeTelevisores){
        numeroDeTelevisores = valorNumeroDeTelevisores;
    }
   
    public void setTipoSalon(String valorTipoSalon){
        tipoSalon = valorTipoSalon;
    }
   
    public int getNumeroDeTelevisores(){return numeroDeTelevisores;}
   
    public String getTipoSalon(){return tipoSalon;}
}

Código del objeto (clase) CocinaCasa:

Código: [Seleccionar]
public class CocinaCasa{
    private boolean esIndependiente;
    private int numeroDeFuegos;
   
    public CocinaCasa(){
        esIndependiente = false;
        numeroDeFuegos = 0;
    }
   
    public CocinaCasa(boolean valorEsIndependiente, int valorNumeroDeFuegos){
        esIndependiente = valorEsIndependiente;
        numeroDeFuegos = valorNumeroDeFuegos;
    }
   
    public void setEsIndependiente(boolean valorEsIndependiente){
        esIndependiente = valorEsIndependiente;
    }
   
    public void setNumeroDeFuegos(int valorNumeroDeFuegos){
        numeroDeFuegos = valorNumeroDeFuegos;
    }
   
    public boolean getEsIndependiente(){return esIndependiente;}
   
    public int getNumeroDeFuegos(){return numeroDeFuegos;}
}

Código del objeto (clase) Casa:

Código: [Seleccionar]
public class Casa{
    private double superficie;
    private String direccion;
    private SalonCasa salonCasa;
    private CocinaCasa cocina;
   
    public Casa(){
        superficie = 0;
        direccion = "";
        salonCasa = new SalonCasa();
        cocina = new CocinaCasa();
    }
   
    public Casa(double valorSuperficie, String valorDireccion, SalonCasa classSalonCasa, CocinaCasa classCocinaCasa){
        superficie = valorSuperficie;
        direccion = valorDireccion;
        salonCasa = new SalonCasa(classSalonCasa.getNumeroDeTelevisores(), classSalonCasa.getTipoSalon());
        cocina = new CocinaCasa(classCocinaCasa.getEsIndependiente(), classCocinaCasa.getNumeroDeFuegos());
    }
}

Quería comentar (consultar) algo. Si en el objeto (clase) CocinaCasa el código es:

Código: [Seleccionar]
public class CocinaCasa{
    private boolean esIndependiente;
    private int numeroDeFuegos;
   
    public CocinaCasa(){
        esIndependiente = false;
        numeroDeFuegos = 0;
    }
   
   
    public void setEsIndependiente(boolean valorEsIndependiente){
        esIndependiente = valorEsIndependiente;
    }
   
    public void setNumeroDeFuegos(int valorNumeroDeFuegos){
        numeroDeFuegos = valorNumeroDeFuegos;
    }
   
    public boolean getEsIndependiente(){return esIndependiente;}
   
    public int getNumeroDeFuegos(){return numeroDeFuegos;}
}

en vez de:

Código: [Seleccionar]
public class CocinaCasa{
    private boolean esIndependiente;
    private int numeroDeFuegos;
   
    public CocinaCasa(){
        esIndependiente = false;
        numeroDeFuegos = 0;
    }
   
    public CocinaCasa(boolean valorEsIndependiente, int valorNumeroDeFuegos){
        esIndependiente = valorEsIndependiente;
        numeroDeFuegos = valorNumeroDeFuegos;
    }
   
    public void setEsIndependiente(boolean valorEsIndependiente){
        esIndependiente = valorEsIndependiente;
    }
   
    public void setNumeroDeFuegos(int valorNumeroDeFuegos){
        numeroDeFuegos = valorNumeroDeFuegos;
    }
   
    public boolean getEsIndependiente(){return esIndependiente;}
   
    public int getNumeroDeFuegos(){return numeroDeFuegos;}
}

No me funciona los constructores en el código del objeto "Casa". Como que tiene que haber un constructor que se le pasan los valores de los atributos por parametros, en las clases usadas, para que funcione también el constructor de los parámetros en la clase que usa.

No sé si me he explicado bien. Creo que mejor lo veréis con los códigos que os he puesto antes. Lo mismo pasa con el código de la clase "SalonCasa". Si le quito el constructor que usa parámetros, tampoco me funciona el constructor con parámetros en la clase "Casa".

Gracias
Título: Re:CU00642B Pasar objetos como parámetros a un método o constructor Java
Publicado por: Dimitar Stefanov en 01 de Marzo 2016, 10:58
Creo que en la siguiente entrega (CU00642B) se aclara mi duda https://www.aprenderaprogramar.com/index.php?option=com_content&view=article&id=523:la-sentencia-new-invocacion-de-un-constructor-para-crear-objetos-en-java-concepto-y-ejemplos-cu00643b&catid=68:curso-aprender-programacion-java-desde-cero&Itemid=188 (https://www.aprenderaprogramar.com/index.php?option=com_content&view=article&id=523:la-sentencia-new-invocacion-de-un-constructor-para-crear-objetos-en-java-concepto-y-ejemplos-cu00643b&catid=68:curso-aprender-programacion-java-desde-cero&Itemid=188)

Exactamente dice:

Citar
nombreDelObjeto = new NombreDeLaOtraClase (parámetros requeridos por el constructor de la otra clase si los hubiera)

 Recordar que la variable nombreDelObjeto contiene una referencia (puntero) al objeto, no el objeto en sí mismo. La instrucción new implica que se producen dos acciones:

a)      Creación de un objeto de un tipo definido por una clase.

b)      Ejecución del constructor asociado.
;

Es decir, para la creación del nuevo objeto se usa el constructor de la clase "usada/referenciada/asociada" no de la clase "que usa/(en mi caso, "Casa")".  Por lo tanto, si tengo:

Código: [Seleccionar]
public Casa(CocinaCasa classCocinaCasa){
        cocina = new CocinaCasa(classCocinaCasa.getEsIndependiente(), classCocinaCasa.getNumeroDeFuegos());
    }

Tengo que ir al código de "CocinaCasa" y ver allí el constructor cómo se ha hecho. Si hay un constructor que no necesita parámetros, como por ejemplo:

Código: [Seleccionar]
public CocinaCasa(){
        esIndependiente = false;
        numeroDeFuegos = 0;
    }


No me funcionará el siguiente constructor en "Casa":

Código: [Seleccionar]
public Casa(CocinaCasa classCocinaCasa){
        cocina = new CocinaCasa(classCocinaCasa.getEsIndependiente(), classCocinaCasa.getNumeroDeFuegos());
    }

Obligatoriamente tiene que existir un constructor de este tipo:

Código: [Seleccionar]
public CocinaCasa(boolean valorEsIndependiente, int valorNumeroDeFuegos){
        esIndependiente = valorEsIndependiente;
        numeroDeFuegos = valorNumeroDeFuegos;
    }


para que funcione el constructor:

Código: [Seleccionar]
public Casa(CocinaCasa classCocinaCasa){
        cocina = new CocinaCasa(classCocinaCasa.getEsIndependiente(), classCocinaCasa.getNumeroDeFuegos());
    }

en la clase "madre", la que hereda (no se si está bien utilizado aquí este término).

Puse este razonamiento porque supongo que a mas de uno le ha surgido.
Título: Re:Java Por qué no funciona una clase si quito constructor en otra clase CU00642B
Publicado por: César Krall en 02 de Marzo 2016, 08:38
Hola! El razonamiento que has hecho es correcto, para invocar un constructor en otra clase, tienes que haber definido un constructor con la misma forma que invocas. Si no está el constructor en la otra clase te saltará un error.

He visto que como pones como nombre de parámetro classSalonCasa, te recomiendo que no uses nombres de este tipo porque class es una palabra reservada del lenguaje y un nombre así resulta confuso. Sería mejor objetoSalonCasa que no da lugar a confusiones.

Por otro lado tu código está incompleto, te faltan los métodos getters y setters de la clase Casa

Saludos!
Título: Re:Java Por qué no funciona una clase si quito constructor en otra clase CU00642B
Publicado por: Dimitar Stefanov en 02 de Marzo 2016, 10:46
Vuelvo a colgar los 3 códigos, porque para que podamos acceder al objeto "SalonCasa" y "CocinaCasa" desde "Casa" y poder modificar sus variables/campos/atributos, tenemos que hacer los mismos como "public". Así que, por lo tanto, los códigos quedarán asi:

Código "SalonCasa":

Código: [Seleccionar]
public class SalonCasa{
    public int numeroDeTelevisores;
    public String tipoSalon;
   
    public SalonCasa(){
        numeroDeTelevisores = 0;
        tipoSalon = "desconocido";
    }
   
    public SalonCasa(int valorNumeroDeTelevisores, String valorTipoSalon){
        numeroDeTelevisores = valorNumeroDeTelevisores;
        tipoSalon = valorTipoSalon;
    }
   
    public void setNumeroDeTelevisores(int valorNumeroDeTelevisores){
        numeroDeTelevisores = valorNumeroDeTelevisores;
    }
   
    public void setTipoSalon(String valorTipoSalon){
        tipoSalon = valorTipoSalon;
    }
   
    public int getNumeroDeTelevisores(){return numeroDeTelevisores;}
   
    public String getTipoSalon(){return tipoSalon;}
}

Código "CocinaCasa":

Código: [Seleccionar]
public class CocinaCasa{
    public boolean esIndependiente;
    public int numeroDeFuegos;
   
    public CocinaCasa(){
        esIndependiente = false;
        numeroDeFuegos = 0;
    }
   
    public CocinaCasa(boolean valorEsIndependiente, int valorNumeroDeFuegos){
        esIndependiente = valorEsIndependiente;
        numeroDeFuegos = valorNumeroDeFuegos;
    }
   
    public void setEsIndependiente(boolean valorEsIndependiente){
        esIndependiente = valorEsIndependiente;
    }
   
    public void setNumeroDeFuegos(int valorNumeroDeFuegos){
        numeroDeFuegos = valorNumeroDeFuegos;
    }
   
    public boolean getEsIndependiente(){return esIndependiente;}
   
    public int getNumeroDeFuegos(){return numeroDeFuegos;}
}

Y, por último, pero no menos importante, el código de "Casa":

Código: [Seleccionar]
public class Casa{
    private double superficie;
    private String direccion;
    private SalonCasa salonCasa;
    private CocinaCasa cocina;
   
    public Casa(){
        superficie = 0;
        direccion = "";
        salonCasa = new SalonCasa();
        cocina = new CocinaCasa();
    }
   
    public Casa(double valorSuperficie, String valorDireccion, SalonCasa classSalonCasa, CocinaCasa classCocinaCasa){
        superficie = valorSuperficie;
        direccion = valorDireccion;
        salonCasa = new SalonCasa(classSalonCasa.getNumeroDeTelevisores(), classSalonCasa.getTipoSalon());
        cocina = new CocinaCasa(classCocinaCasa.getEsIndependiente(), classCocinaCasa.getNumeroDeFuegos());
    }
   
    public void setSuperficie(double valor_superficie){
        superficie = valor_superficie;
    }
   
    public void setDireccion(String valor_direccion){
        direccion = valor_direccion;
    }
   
    public void setSalonCasa(int valor_numeroDeTelevisores, String valor_tipoSalon){
        salonCasa.numeroDeTelevisores = valor_numeroDeTelevisores;
        salonCasa.tipoSalon = valor_tipoSalon;
    }
   
    public void setCocina(boolean valor_esIndependiente, int valor_numeroDeFuegos){
        cocina.esIndependiente = valor_esIndependiente;
        cocina.numeroDeFuegos = valor_numeroDeFuegos;
    }
   
    public double getSuperficie(){return superficie;}
   
    public String getDireccion(){return direccion;}
   
    public SalonCasa getSalonCasa(){return salonCasa;}
   
    public CocinaCasa getCocina(){return cocina;}
}

Creo que ahora está muuuuucho mejor :)

Gracias
Título: Re:Java Por qué no funciona una clase si quito constructor en otra clase CU00642B
Publicado por: César Krall en 03 de Marzo 2016, 08:27
Hola! Los métodos como setSalonCasa no los tienes bien definidos. Una clase opera solo con sus atributos, en este caso el atributo es un objeto de tipo SalonCasa y eso sería lo que debe recibir el método (no un número de televisores y un tipo de salón que son atributos de otra clase).

Consulta las explicaciones en https://www.aprenderaprogramar.com/foros/index.php?topic=1220.0

Y en https://www.aprenderaprogramar.com/foros/index.php?topic=1238.0

Ahí hay explicaciones de interés en relación con estos ejercicios

Saludos!
Título: Re:Java Por qué no funciona una clase si quito constructor en otra clase CU00642B
Publicado por: Dimitar Stefanov en 03 de Marzo 2016, 11:18
Buenas, César.

Gracias por la corrección.

Me he leído los enlaces que me recomiendas y sobre todo este:

https://www.aprenderaprogramar.com/foros/index.php?topic=1220.0 (https://www.aprenderaprogramar.com/foros/index.php?topic=1220.0)

He optado por la siguiente manera: (sólo cuelgo el código de "Casa")

Código: [Seleccionar]
public class Casa{
    private double superficie;
    private String direccion;
    private SalonCasa salonCasa;
    private CocinaCasa cocina;
   
    public Casa(){
        superficie = 0;
        direccion = "";
        salonCasa = new SalonCasa();
        cocina = new CocinaCasa();
    }
   
    public Casa(double valorSuperficie, String valorDireccion, SalonCasa classSalonCasa, CocinaCasa classCocinaCasa){
        superficie = valorSuperficie;
        direccion = valorDireccion;
        salonCasa = new SalonCasa(classSalonCasa.getNumeroDeTelevisores(), classSalonCasa.getTipoSalon());
        cocina = new CocinaCasa(classCocinaCasa.getEsIndependiente(), classCocinaCasa.getNumeroDeFuegos());
    }
   
    public void setSuperficie(double valor_superficie){
        superficie = valor_superficie;
    }
   
    public void setDireccion(String valor_direccion){
        direccion = valor_direccion;
    }
   
   
   
    public void setSalonCasa(SalonCasa objetoSalon){
       salonCasa = new SalonCasa();
       salonCasa.setNumeroDeTelevisores(objetoSalon.getNumeroDeTelevisores());
       salonCasa.setTipoSalon(objetoSalon.getTipoSalon());
    }
   
     public void setCocina(CocinaCasa objetoCocina){
        cocina = new CocinaCasa();
        cocina.setEsIndependiente(objetoCocina.getEsIndependiente());
        cocina.setNumeroDeFuegos(objetoCocina.getNumeroDeFuegos());
     }
   
    public double getSuperficie(){return superficie;}
   
    public String getDireccion(){return direccion;}
   
    public SalonCasa getSalonCasa(){return salonCasa;}
   
    public CocinaCasa getCocina(){return cocina;}
}

De este código no entiendo: si hemos creado ya en el contructor un nuevo objeto que es "salonCasa" y "cocina" por qué los velvemos a crear en el método "setSalonCasa" y "setCocina", respectivamente. Y por qué como parámetros le pasamos los métodos "getNumeroDeTelevisores()", "getTipoSalon()", "getEsIndependiente()" y "getNumeroDeFuegos()". (Me baso en lo que ha explicado Mario R. Rancel en el hilo que te comenté).

Gracias
Título: Re:Java Por qué no funciona una clase si quito constructor en otra clase CU00642B
Publicado por: César Krall en 05 de Marzo 2016, 17:48
Hola! Quizás se hace un poco complejo ahora pero a medida que trabajes con objetos lo irás entendiendo todo. Piensa en un objeto como una caja dentro de la cual hay cosas (atributos y métodos). Ahora creas un objeto, una caja, y dentro tienes un cuchillo, una botella y otra caja, es decir, otro objeto, que tiene dentro tres monedas y un alfiler por decir algo.

Cada vez que creas un objeto, tienes de partida todos esos elementos (según indica el constructor). Ahora resulta que te llega por parámetro para el método set un objeto que tiene dentro cinco monedas y dos alfileres. ¿Qué puedes hacer?

a) Puedes sacar la caja con tres monedas y un alfiler, y a cambio poner la caja con cinco monedas y dos alfileres.

El problema es que en Java todo son referencias. Al poner la caja con cinco monedas y dos alfileres realmente no ponemos la caja, sino una referencia a la caja. La caja sería única, pero varias personas tienen la llave de la caja (referencia) de modo que si una manipula la caja, la otra persona cuando llegue se va a encontrar que alguien hizo un cambio pero a lo mejor una de las personas con la referencia no quería que otra persona hiciera cambios.

En resumen, supón que tenemos 4 objetos y en los cuatro pasamos como parámetro para un set la caja con cinco monedas y dos alfileres. Ahora en uno de esos 4 objetos hacemos una manipulación y dejamos 2 monedas y 2 alfileres. Sólo hemos hecho la manipulación desde uno de los objetos, pero como los otros tienen todos la referencia en vez del objeto en sí, cuando vayan a buscar se encontrarán que hay 2 monedas en lugar de las cinco que esperaban.

Esto muchas veces no se quiere que suceda. ¿Qué se hace entonces?

b) Cuando me llega como parámetro de un método set no me quedo con la referencia, sino que digo: creo un objeto nuevo, cocina = new CocinaCasa();

Ahora dentro del nuevo objeto nuevo coloco una copia de lo que había en el objeto recibido por referencia:

        cocina.setEsIndependiente(objetoCocina.getEsIndependiente());
        cocina.setNumeroDeFuegos(objetoCocina.getNumeroDeFuegos());

Ya tengo un objeto que es igual al recibido por parámetro pero que es un nuevo objeto, tiene una nueva referencia (en memoria). De modo que si ahora manipulamos el nuevo objeto creado, sólo lo afectamos a él, porque tiene una referencia única (nueva que hemos creado, puesto que hemos creado un nuevo objeto).

Como te decía puede ser un poco confuso, trata de ir leyendo más hilos del foro (encontrarás muchas explicaciones interesantes) y seguir avanzando y haciendo ejercicios entendiendo lo que haces, si tienes dudas vete consultando para intentar comprender todo lo que se trabaja en el curso.

Saludos!
Título: Re:Java Por qué no funciona una clase si quito constructor en otra clase CU00642B
Publicado por: Dimitar Stefanov en 05 de Marzo 2016, 21:29
Buenas, César.

Primo, y ante nada, quería agradecerte la extensa y compensiva explicación. Realmente quería entender tu ejemplo, así que de verdad cogí 2 cojas (una más pequeña que la otra), puse dentro varios objetos e hice las instrucciones, jejeje. Es que como Java y los objetos son cosas tan abstractas, viéndolo se entiend mejor :)

A veces estoy un día entero con un ejercicio y no me muevo hasta que lo entienda, pero es que única y exclusivamente así avanzaré, entendiendo las cosas.

Sí, resulta muy confuso al principio, pero poco a poco se te aclaran las cosas.

Gracias.
Título: Re:Java Por qué no funciona una clase si quito constructor en otra clase CU00642B
Publicado por: César Krall en 07 de Marzo 2016, 08:46
Hola! Es mejor que te detengas para intentar entender bien los ejercicios y hacer pocos ejercicios que intentar correr y hacer muchos ejercicios que no entiendas bien. Lo que no entiendas bien te servirá de poco y se te olvidará. Saludos!
Título: Re:Java Por qué no funciona una clase si quito constructor en otra clase CU00642B
Publicado por: Dimitar Stefanov en 07 de Marzo 2016, 10:14
Totalmente de acuerdo, César.

Un saludo