Autor Tema: Clases anidadas  (Leído 1862 veces)

drate

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 24
    • Ver Perfil
Clases anidadas
« en: 11 de Julio 2023, 20:45 »
Buenas tardes.
He estoy haciendo este ejercicio de clases anidadas y no consigo verlo del todo claro.
Lo dejo por si me podéis echar una mano.
Muchas gracias. Un saludo.

Define e implementa una clase para definir la estructura de un Coche. La idea es que la clase tenga unos pocos atributos como:
• matricula
• marca
• modelo
• potencia
• velocidadMaxima
Y guardar información, de algunos componentes que lo forman, teniendo en cuenta que un coche tendrá 1 chasis y 4 ruedas:
Del chasis guardaremos:
• material
• peso

De cada rueda:
• medida
• tipo (“seco”, “lluvia”)
• marca
• modelo
Una vez definida la estructura, prepara un programa principal donde crees un par de objetos de la clase Coche con información para
todas las partes

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 989
    • Ver Perfil
Re: Clases anidadas
« Respuesta #1 en: 12 de Julio 2023, 11:16 »
Aquí tenemos tres entidades.

Dos de esas entidades son:

Citar
Chasis
- String material
- double peso

Citar
Rueda
- double medida
- String tipo
- String marca
- String modelo

Estas dos entidades, estarán incluidas como atributos de la tercera entidad, llamada Coche, que será la clase principal.

Sabemos que un Coche tiene 1 Chasis y 4 Ruedas. Así que respecto a las "ruedas" hay que decidir cómo queremos incluirla en la lista de atributos.
Podemos simplemente introducir 4 atributos de este tipo:
Citar
Coche
- String matricula
- String marca
- String modelo
- int potencia
- int velocidadMaxima
- Chasis chasis
- Rueda ruedaDelIzq
- Rueda ruedaDelDer
- Rueda ruedaTrasIzq
- Rueda ruedaTrasDer

O podemos incluirlas como un array, que luego en el constructor de clase podremos inicializarlo para que tenga 4 elementos

Citar
Coche
- String matricula
- String marca
- String modelo
- int potencia
- int velocidadMaxima
- Chasis chasis
- Rueda[] ruedas

Cualquier opción es buena, tan solo habrá que tener en cuenta que si optamos por usar un array, habrá que usar índices (0,1,2,3) para apuntar a cada rueda en concreto.


Estas tres clases, pueden escribirse cada una en un archivo .java individual por separado.
Pero, teniendo en cuenta que para este caso Chasis y Rueda no tienen mucho sentido como entidades separadas (si por ejemplo fuese un programa para un taller que vende ruedas, entonces esta clase sí tendría sentido como entidad individual), también se puede optar por escribirlo todo en un único archivo .java.

La clase principal sería Coche. Y dentro de su cuerpo, además de atributos, constructores y métodos..., se podrían escribir también las clases Chasis y Rueda, teniendo cada una su propio cuerpo con sus propios atributos, constructores y métodos.
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

drate

  • Sin experiencia
  • *
  • APR2.COM
  • Mensajes: 24
    • Ver Perfil
Re: Clases anidadas
« Respuesta #2 en: 13 de Julio 2023, 17:01 »
Buenas tardes.
La duda que tengo es como declaro el constructor en la clase contenedora y le paso datos al mismo tiempo a todas las clases.

package Practica1;

public class Coche {
   private String matricula;
   private String marca;
   private String modelo;
   private int potencia;
   private int velocidadMaxima;
   Rueda rueda;
   Chasis chasis;

   public Coche(String matricula, String marca, String modelo, int potencia, int velocidadMaxima) {
      super();
      this.matricula = matricula;
      this.marca = marca;
      this.modelo = modelo;
      this.potencia = potencia;
      this.velocidadMaxima = velocidadMaxima;
      // this.rueda = rueda;
      // this.chasis = chasis;
   }

   public String getMatricula() {
      return matricula;
   }

   public void setMatricula(String matricula) {
      this.matricula = matricula;
   }

   public String getMarca() {
      return marca;
   }

   public void setMarca(String marca) {
      this.marca = marca;
   }

   public String getModelo() {
      return modelo;
   }

   public void setModelo(String modelo) {
      this.modelo = modelo;
   }

   public int getPotencia() {
      return potencia;
   }

   public void setPotencia(int potencia) {
      this.potencia = potencia;
   }

   public int getVelocidadMaxima() {
      return velocidadMaxima;
   }

   public void setVelocidadMaxima(int velocidadMaxima) {
      this.velocidadMaxima = velocidadMaxima;
   }

   public class Chasis {

      public String material;
      public Double peso;

      public Chasis(String material, Double peso) {
         super();
         this.material = material;
         this.peso = peso;
      }

      public String getMaterial() {
         return material;
      }

      public void setMaterial(String material) {
         this.material = material;
      }

      public Double getPeso() {
         return peso;
      }

      public void setPeso(Double peso) {
         this.peso = peso;
      }

   }

   public class Rueda {

      public int medida;
      public String tipo; // (“seco”, “lluvia”)
      public String marca;
      public String modelo;
      public String caracteristicas;

      public Rueda(int medida, String tipo, String marca, String modelo) {
         super();
         this.medida = medida;
         this.tipo = caracteristicas;
         this.marca = marca;
         this.modelo = modelo;
      }

      public int getMedida() {
         return medida;
      }

      public void setMedida(int medida) {
         this.medida = medida;
      }

      public String getTipo() {
         return tipo;
      }

      public void setTipo(String tipo) {
         this.tipo = tipo;
      }

      public String getMarca() {
         return marca;
      }

      public void setMarca(String marca) {
         this.marca = marca;
      }

      public String getModelo() {
         return modelo;
      }

      public void setModelo(String modelo) {
         this.modelo = modelo;
      }

      public String getCaracteristicas() {
         return caracteristicas;
      }

      public void setCaracteristicas(String caracteristicas) {
         this.caracteristicas = caracteristicas;
      }

   }

   @Override
   public String toString() {
      return "Coche [matricula=" + matricula + ", marca=" + marca + ", modelo=" + modelo + ", potencia=" + potencia
            + ", velocidadMaxima=" + velocidadMaxima + ", rueda=" + rueda + ", chasis=" + chasis + "]";
   }

}

package Practica1;

public class Main {

   public static void main(String[] args) {
      Coche t= new Coche("1998DTM","Jaguar","X-Type",280,250);
      Coche.Chasis t= new ("carbono",159.2);
      
   }
}

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 989
    • Ver Perfil
Re: Clases anidadas
« Respuesta #3 en: 14 de Julio 2023, 01:44 »
Hola

Lo primero, el coche ha de tener 4 ruedas, así que o ponemos 4 atributos de clase Rueda, o ponemos un array de dicha clase.
Ah, y salvo que haya un motivo de peso, los atributos de chasis y ruedas también deben ser privados.

Citar
public class Coche {
   
      private String matricula;
      private String marca;
      private String modelo;
      private int potencia;
      private int velocidadMaxima;
      private Rueda[] ruedas;
      private Chasis chasis;

Los atributos de las clases Chasis y Rueda también es recomendable que sean privados.


Ahora, cómo construir un coche... aquí efectivamente es donde se presenta el problema.

Las clases Chasis y Rueda están anidadas dentro de Coche, por tanto, por sí solas no pueden existir.
Para que existan y puedan ser invocadas, primero hay que instanciar un objeto Coche.
Por tanto, en el constructor de coche no pondremos que reciban argumentos para chasis y ruedas, porque para disponer de ellos primero hay que construir el propio coche.

Lo que sí haremos será dotar a la clase de unos setters para, después de haber creado el coche, poder crear y asignarle chasis y ruedas.
Código: [Seleccionar]
public class Coche {

private String matricula;
private String marca;
private String modelo;
private int potencia;
private int velocidadMaxima;
private Rueda[] ruedas;
private Chasis chasis;

//Constructor no recibe ni ruedas ni chasis
public Coche(String matricula, String marca, String modelo, int potencia, int velocidadMaxima) {
this.matricula = matricula;
this.marca = marca;
this.modelo = modelo;
this.potencia = potencia;
this.velocidadMaxima = velocidadMaxima;
}

//Chasis y ruedas llegarán por setters
public void setChasis(Chasis chasis) {
this.chasis = chasis;
}

public void setRuedas(Rueda[] ruedas) {
this.ruedas = ruedas;
}


Ahora en el Main ya podemos crear todo lo necesario.
Primero el coche.
Luego, gracias a que tenemos un coche, podemos crear ruedas y chasis
Por último, asignamos ese chasis y ruedas, al coche creado.

Fíjate en el código, que para indicar el tipo del objeto que vamos a crear llamamos a los nombres de clases Coche.Rueda y Coche.Chasis
Pero para construir los objetos, llamamos al nombre del objeto coche instanciado y a través de él podemos instancias los objetos de las clases anidadas.

Citar
public class Main {

   public static void main(String[] args) {
      
      //Primero creamos coche
      Coche coche = new Coche("1998DTM","Jaguar","X-Type",280,250);

      //Ahora, usando la instancia de Coche, podemos crear Ruedas y Chasis
      Coche.Chasis chasis = coche.new Chasis("Carbono", 159.2);
      
      Coche.Rueda[] ruedas = new Coche.Rueda[] {
            //Ruedas delanteras
            coche.new Rueda(145, "Seco", "Dunlop", "Eco Control"),
            coche.new Rueda(145, "Seco", "Dunlop", "Eco Control"),
            //Ruedas traseras
            coche.new Rueda(165, "Seco", "Dunlop", "Sport Max Race"),
            coche.new Rueda(165, "Seco", "Dunlop", "Sport Max Race")
      };
      
      //Tras crearlos, podemos asignarlo a la instancia de Coche
      coche.setChasis(chasis);
      coche.setRuedas(ruedas);
   }

}


Como puedes ver, esto de las clases anónimas es un poco lioso y por lo general vamos a preferir usarlas en casos especiales, sobre todo cuando no se requieran datos externos a la clase que las contiene.
Es decir, todo lo necesario para crear una clase anónima, ya existe dentro de la clase principal contenedora y por lo tanto no hay necesidad de invocarlas fuera de dicha clase.

En este caso, para crear chasis y ruedas, se necesitan datos externos. Se supone que habrá un usuario tecleando los datos de las ruedas y de los diferentes chasis, así que para ir creando objetos con esos datos necesitamos poder invocar a la clase Rueda y Chasis desde la clase "main" donde se están pidiendo datos al usuario.
Es entonces cuando hay que complicarse con los nombres compuestos de dos (o más) clases separadas por puntos y la necesidad de instancia primero las clases "contenedoras" para luego poder llamar a las clases "anidadas".

En casos así, vamos a preferir escribir las distintas clases por separado, en lugar de anidarlas.
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

 

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