Autor Tema: Pasar objetos como parámetros a un método o constructor Java. Diferenciar objeto  (Leído 4461 veces)

micaelasol

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 33
    • Ver Perfil
Aquí va la respuesta que he podido lograr del ejercicio (CU00642B). En la clase "Casa" me aparece un error, y no puedo solucionarlo.
Citar
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: [Seleccionar]
public class SalonCasa1{
    private int numeroDeTelevisores;
    private String tipoSalon;
   
    public SalonCasa1(){
        numeroDeTelevisores=0;
        tipoSalon="";}
   
    public SalonCasa1(String valorTipoSalon, int valorNumeroDeTelevisores){
        tipoSalon=valorTipoSalon;
        numeroDeTelevisores=valorNumeroDeTelevisores;}
   
    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: [Seleccionar]
public class CocinaCasa1{
    private boolean esIndependiente;
    private int numeroDeFuegos;
   
    public CocinaCasa1(){
        esIndependiente=false;
        numeroDeFuegos=0;}
       
    public CocinaCasa1(boolean valorEsIndependiente, int valorNumeroDeFuegos){
        esIndependiente=valorEsIndependiente;
        numeroDeFuegos=valorNumeroDeFuegos;}

    public void setEsIndependienten(boolean valorEsIndependiente){
        esIndependiente=valorEsIndependiente;}
   
    public void setnumeroDeFuegos(int valorNumeroDeFuegos){
        numeroDeFuegos=valorNumeroDeFuegos;}
       
    public boolean getEsIndependiente(){return esIndependiente;}
   
    public int getNumeroDeFuegos(){return numeroDeFuegos;}
}

Código: [Seleccionar]
public class Casa1{
    private double superficie;
    private String direccion;
    private SalonCasa1 salon;
    private CocinaCasa1 cocina;
   
    public Casa1(){
        superficie=0.0;
        direccion="";
        salon=new SalonCasa1();
        cocina=new CocinaCasa1();}
       
    public[color=red] c[/color]asa1(double valorSuperficie, String valorDireccion, SalonCasa1 objetoSalon, CocinaCasa1 objetoCocina){
        superficie=valorSuperficie;
        direccion=valorDireccion;
        salon=new SalonCasa1(objetoSalon.getNumeroDeTelevisores(), objetoSalon.getTipoSalon());
        cocina=new CocinaCasa1(objetoCocina.getEsIndependiente(), objetoCocina.getNumeroDeFuegos());}
   
    public void setSuperficie(double valorSuperficie){
        superficie=valorSuperficie;}
       
    public void setDireccion(String valorDireccion){
        direccion=valorDireccion;}   
       
    public double getSuperficie(){return superficie;}
   
    public String getDireccion(){return direccion;}
}

En donde esta rojo, en la clase Casa, es donde me aparece un error de tipo: "invalid method declaration; return type required". No se como solucionarlo, agradecería si me ayudarían.
Gracias!

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 989
    • Ver Perfil
Citar
    public casa1(double valorSuperficie, String valorDireccion, SalonCasa1 objetoSalon, CocinaCasa1 objetoCocina){
        superficie=valorSuperficie;
        direccion=valorDireccion;
        salon=new SalonCasa1(objetoSalon.getNumeroDeTelevisores(), objetoSalon.getTipoSalon());
        cocina=new CocinaCasa1(objetoCocina.getEsIndependiente(), objetoCocina.getNumeroDeFuegos());}


El error se debe a que esa 'c' la has puesto en minúscula. Al ponerla así, no coincide con el nombre de la clase Casa1 y entonces Java no lo considera un constructor, si no un método cualquiera y se queja porque no se le ha puesto ningún tipo de retorno (void, int, String, etc...) ya que un método siempre ha de tener un retorno.

Cambia esa 'c' por una mayúscula y solucionado.

Por cierto, el enunciado pide que el constructor por defecto de SalonCasa, inicialice el tipo de salón como "desconocido".


Código: [Seleccionar]
public SalonCasa1(){
    numeroDeTelevisores=0;
    tipoSalon="Desconocido";}

Inicializarlo con cadena vacía está bien y además suele ser lo habitual.
Pero en este caso nos piden hacerlo de manera distinta.
« Última modificación: 07 de Agosto 2022, 12:53 por Kabuto »
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 989
    • Ver Perfil
Más cosas a comentar ahora que veo a fondo tu código.

Mucho ojo con el orden en que ponemos los parámetros para los constructores.
Para la clase SalonCasa, has puesto que primero recibe el String de tipoSalon y luego el int de numero televisores:

Código: [Seleccionar]
    public SalonCasa(String valorTipoSalon, int valorNumeroDeTelevisores){
        tipoSalon=valorTipoSalon;
        numeroDeTelevisores=valorNumeroDeTelevisores;}

Vale, eso está muy bien, pero luego cuando quieras construir un objeto de esta clase, recuerda que los parámetros ha de recibirlo en ese mismo orden.

Porque en la clase Casa, en el constructor donde construyes un SalonCasa, se los estás pasando invertidos. Y Java también se quejará por esto:
Citar
    public Casa(double valorSuperficie, String valorDireccion, SalonCasa objetoSalon, CocinaCasa objetoCocina){
        superficie=valorSuperficie;
        direccion=valorDireccion;
        salon=new SalonCasa(objetoSalon.getNumeroDeTelevisores(), objetoSalon.getTipoSalon());
        cocina=new CocinaCasa(objetoCocina.getEsIndependiente(), objetoCocina.getNumeroDeFuegos());}

Hay que dárselos en el orden correcto:
Citar
    public Casa(double valorSuperficie, String valorDireccion, SalonCasa objetoSalon, CocinaCasa objetoCocina){
        superficie=valorSuperficie;
        direccion=valorDireccion;
        salon=new SalonCasa(objetoSalon.getTipoSalon(), objetoSalon.getNumeroDeTelevisores());
        cocina=new CocinaCasa(objetoCocina.getEsIndependiente(), objetoCocina.getNumeroDeFuegos());}


Sigamos hablando de este constructor, porque has hecho algo que es muy interesante de comentar.
La forma en que tu constructor inicializa los objetos salon y cocina:
Citar
    public Casa(double valorSuperficie, String valorDireccion, SalonCasa objetoSalon, CocinaCasa objetoCocina){
        superficie=valorSuperficie;
        direccion=valorDireccion;
        salon=new SalonCasa(objetoSalon.getTipoSalon(), objetoSalon.getNumeroDeTelevisores());
        cocina=new CocinaCasa(objetoCocina.getEsIndependiente(), objetoCocina.getNumeroDeFuegos());
}

Haciéndolo de esa manera, has de tener en cuenta que estás creando NUEVOS objetos a partir de los que has recibido entre paréntesis.
Es decir, van a tener los mismos valores para los atributos, pero no serán IGUALES. Serán objetos distintos.
Esto no es necesariamente un problema. Habrá ocasiones en que precisamente nos interese hacerlo así, pero normalmente NO.

Cuando un constructor recibe objetos entre paréntesis, normalmente se asignan esos mismos objetos a los atributos, sin crear unos nuevos a partir de ellos:
Citar
    public Casa(double valorSuperficie, String valorDireccion, SalonCasa objetoSalon, CocinaCasa objetoCocina){
        superficie=valorSuperficie;
        direccion=valorDireccion;
        salon=objetoSalon;
        cocina=objetoCocina;}

¿Ves? Entre paréntesis hemos recibido unas "referencias" a unos objetos, y esas mismas referencias las asignamos a los atributos.
Y ya está, con esto es suficiente.

Pero tú lo que has hecho ha sido coger los "valores" de esas referencias, y usarlos para crear objetos nuevos

En otros lenguajes como C/C++, hay de hecho instrucciones específicas para indicar si un parámetro queremos pasarlo por "referencia" o por "valor".
En Java no las hay, simplificaron este aspecto.
Los datos primitivos (int, double, char...) se pasan por "valor" y los objetos de clase se pasan por "referencia".

Lo que tú has hecho ha sido una forma artificial de pasar por "valor" algo que Java solo permite pasar por "referencia"

¿Esto es incorrecto?
No, para nada. Pero implica unas diferencias que debemos tener en cuenta.

Al pasar por referencia un objeto externo y asignarlo a los atributos de otro objetos (que es lo habitual), esos objetos quedan conectados.
Es decir, para construir una Casa, primero he tenido que construir un SalonCasa.
Son objetos distintos, pero Casa incluye en su interior un SalonCasa.
Entonces, si pasamos por referencia, los cambios que ocurran en el objeto externo SalonCasa también quedarán reflejados en el atributo interno del objeto Casa

Esto se verá mucho mejor con un ejemplo.
Mira, aquí estoy creando un salon y una cocina.
Luego creo una casa y a su constructor les paso ese salon y cocina.

Y le pido a casa que muestre los valores de su nuevo salon y cocina (por cierto, a tu clase Casa le faltan setters y getters para los atributos de Salon y Cocina)

Después de mostrarlos, modifico los valores del salon y de la cocina.

Y vuelvo a pedir a  casa que muestre de nuevo sus valores de salon y cocina.
Código: [Seleccionar]
public class Prueba {

public static void main(String[] args) {

SalonCasa miSalon = new SalonCasa("Gigante", 10);
CocinaCasa miCocina = new CocinaCasa(true, 100);

Casa miCasa = new Casa(300, "Calle Paraiso", miSalon, miCocina);

System.out.println("Televisores: " + miCasa.getSalon().getNumeroDeTelevisores());
System.out.println("Fuegos: " + miCasa.getCocina().getNumeroDeFuegos());

//Cambiamos valores de miSalon y miCocina
miSalon.setNumeroDeTelevisores(3);
miCocina.setnumeroDeFuegos(4);
System.out.println("\n--Valores de salon y cocina cambiados --\n");

System.out.println("Televisores: " + miCasa.getSalon().getNumeroDeTelevisores());
System.out.println("Fuegos: " + miCasa.getCocina().getNumeroDeFuegos());
}

}

Resultado en pantalla:
Citar
Televisores: 10
Fuegos: 100

--Valores de salon y cocina cambiados --

Televisores: 3
Fuegos: 4

Fíjate que casa muestra el cambio de valores, a pesar de que en el objeto casa no hemos hecho cambios.
Los cambios los hemos hecho en los objetos salon y cocina, pero como casa tiene "referencias" a esos objetos, pues casa se verá afectada por esos cambios.


Ahora vamos a hacer exactamente el mismo ejercicio, pero usando el constructor que tú habías escrito.
Es decir, no vamos a pasar por "referencia", si no que de forma artificial vamos pasar por "valor".
¿Cuál será el resultado en pantalla?
Citar
Televisores: 10
Fuegos: 100

--Valores de salon y cocina cambiados --

Televisores: 10
Fuegos: 100

 :o ¡Oh!
El resultado es distinto. Esta vez los cambios que hemos hecho en cocina y salon, no han afectado al objeto casa.
Y esto es porque en tu constructor no asignabas la "referencia" recibida entre paréntesis, si no que construías objetos totalmente nuevos con los "valores" de esas "referencias".

Y vuelvo a preguntar, ¿esto es un problema?
Podría serlo.

Imagina que tenemos un objeto Alumno, que representa a "Juanito" y que vive en la calle "Las Flores".

Y tenemos una clase llamada Curso, donde tenemos insertados a 25 alumnos, entre ellos a "Juanito"

Supongamos que ahora "Juanito" se muda de domicilio y ahora vive en la calle "Las Cortes"

Si cambiamos este dato en el objeto que representa a "Juanito", y resulta que al objeto Curso lo habíamos pasado por "valor" y no por "referencia", tendremos el problema de que el "Juanito" que está dentro de Curso tiene el domicilio antiguo a diferencia del objeto "Juanito" que es externo a Curso.

Esto es un problema, en un sistema informático no podemos consentir esta discrepancia de datos.
Es que además "Juanito" puede estar insertado en múltiples objetos además de Curso. Puede estar insertado en un objeto que agrupe a los alumnos que hacen actividades extraescolares, otro objeto que agrupe alumnos que han solicitado beca, etc...

Cada vez que un alumno cambie de domicilio, no podemos ir rastreando todos los objetos donde ande insertado para cambiarle a todos ese dato.

Por eso es mejor pasar los objetos por "referencia", porque así haciendo un único cambio, este se verá reflejado en todos demás objetos donde pueda estar insertado.

Habrá ocasiones donde sí vamos a querer hacer una copia del "valor" un objeto para que no compartan "referencia" y sean objetos independientes.
Pero no es lo habitual.


Disculpa si me he extendido demasiado con explicaciones.
Pero no quería decirte simplemente "así no se hace, hazlo asá..."
Quería explicarte el motivo y es que además este es un tema que no es fácil de entender al principio.

El asunto de pasar datos por "valor o por "referencia" da para mucha literatura. Así que no te preocupes si aún no te ha quedado claro. Tampoco es algo que deba preocuparte mucho ahora mismo.

Simplemente recuerda que cuando recibas objetos en un constructor, salvo casos muy concretos, lo que vamos a hacer es asignar directamente esas referencias a los atributos.
Citar
public Casa(double valorSuperficie, String valorDireccion, SalonCasa objetoSalon, CocinaCasa objetoCocina){
        superficie=valorSuperficie;
        direccion=valorDireccion;
        salon=objetoSalon;
        cocina=objetoCocina;
}
« Última modificación: 07 de Agosto 2022, 14:09 por Kabuto »
NO respondo dudas por mensaje privado
Publicando vuestras dudas en el foro público conseguimos:
- Que más gente aporte respuestas mejores o complementarias.
- Que otras personas puedan aprender de vuestras dudas.

Mejor en PÚBLICO que en privado. Gracias

micaelasol

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 33
    • Ver Perfil
Gracias a vos por la explicación. Me aseguraré de corregir ese error! Graciass

 

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