Autor Tema: Java Por qué no funciona una clase si quito constructor en otra clase CU00642B  (Leído 4599 veces)

Dimitar Stefanov

  • Experto
  • *****
  • Mensajes: 598
    • Ver Perfil
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
« Última modificación: 02 de Marzo 2016, 08:34 por César Krall »

Dimitar Stefanov

  • Experto
  • *****
  • Mensajes: 598
    • Ver Perfil
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

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.

César Krall

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 2078
  • No vales por lo que dices, sino por lo que haces
    • Ver Perfil
    • aprenderaprogramar.com
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!
Responsable de departamento de producción aprenderaprogramar.com

Dimitar Stefanov

  • Experto
  • *****
  • Mensajes: 598
    • Ver Perfil
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

César Krall

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 2078
  • No vales por lo que dices, sino por lo que haces
    • Ver Perfil
    • aprenderaprogramar.com
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!
Responsable de departamento de producción aprenderaprogramar.com

Dimitar Stefanov

  • Experto
  • *****
  • Mensajes: 598
    • Ver Perfil
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

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
« Última modificación: 05 de Marzo 2016, 17:34 por César Krall »

César Krall

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 2078
  • No vales por lo que dices, sino por lo que haces
    • Ver Perfil
    • aprenderaprogramar.com
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!
Responsable de departamento de producción aprenderaprogramar.com

Dimitar Stefanov

  • Experto
  • *****
  • Mensajes: 598
    • Ver Perfil
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.

César Krall

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 2078
  • No vales por lo que dices, sino por lo que haces
    • Ver Perfil
    • aprenderaprogramar.com
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!
Responsable de departamento de producción aprenderaprogramar.com

Dimitar Stefanov

  • Experto
  • *****
  • Mensajes: 598
    • Ver Perfil
Totalmente de acuerdo, César.

Un saludo

 

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".