Autor Tema: Java Ejemplo herencia simple, extends y super para invocar superclase CU00687B  (Leído 5571 veces)

Dimitar Stefanov

  • Experto
  • *****
  • Mensajes: 598
    • Ver Perfil
Hola.

Aquí expongo una posible solución del ejercicio CU00687B del curso Java desde cero.

Citar
EJERCICIO

Se plantea desarrollar un programa Java que permita la gestión de una empresa agroalimentaria que trabaja con tres tipos de productos: productos frescos, productos refrigerados y productos congelados. Todos los productos llevan esta información común: fecha de caducidad y número de lote. A su vez, cada tipo de producto lleva alguna información específica. Los productos frescos deben llevar la fecha de envasado y el país de origen. Los productos refrigerados deben llevar el código del organismo de supervisión alimentaria, la fecha de envasado, la temperatura de mantenimiento recomendada y el país de origen. Los productos congelados deben llevar la fecha de envasado, el país de origen y la temperatura de mantenimiento recomendada.

Hay tres tipos de productos congelados: congelados por aire, congelados por agua y congelados por nitrógeno. Los productos congelados por aire deben llevar la información de la composición del aire con que fue congelado (% de nitrógeno, % de oxígeno, % de dióxido de carbono y % de vapor de agua). Los productos congelados por agua deben llevar la información de la salinidad del agua con que se realizó la congelación en gramos de sal por litro de agua. Los productos congelados por nitrógeno deben llevar la información del método de congelación empleado y del tiempo de exposición al nitrógeno expresada en segundos.

Crear el código de las clases Java implementando una relación de herencia siguiendo estas indicaciones:

a) En primer lugar realizar un esquema con papel y bolígrafo donde se represente cómo se van a organizar las clases cuando escribamos el código. Estudiar los atributos de las clases y trasladar a la superclase todo atributo que pueda ser trasladado.

b) Crear superclases intermedias (aunque no se correspondan con la descripción dada de la empresa) para agrupar atributos y métodos cuando sea posible. Esto corresponde a “realizar abstracciones” en el ámbito de la programación, que pueden o no corresponderse con el mundo real.

c) Cada clase debe disponer de constructor y permitir establecer (set) y recuperar (get) el valor de sus atributos y tener un método que permita mostrar la información del objeto cuando sea procedente.

Crear una clase testHerencia3 con el método main donde se creen: dos productos frescos, tres productos refrigerados y cinco productos congelados (2 de ellos congelados por agua, otros 2 por agua y 1 por nitrógeno). Mostrar la información de cada producto por pantalla.

El código de la clase "Producto":

Código: [Seleccionar]
public class Producto{
    private String fechaCaducidad;
    private int numeroLote;
   
    public Producto(String fechaCaducidad, int numeroLote){
        this.fechaCaducidad = fechaCaducidad;
        this.numeroLote = numeroLote;
    }
   
    public void setFechaCaducidad(String fechaCaducidad){
        this.fechaCaducidad = fechaCaducidad;
    }
   
    public void setNumeroLote(int numeroLote){
        this.numeroLote = numeroLote;
    }
   
    public String getFechaCaducidad(){return fechaCaducidad;}
    public int getNumeroLote(){return numeroLote;}
   
    public void mostrarInfoProducto(){
        System.out.println("El producto: "+getNumeroLote()+" tiene una fecha de caducidad: "+getFechaCaducidad());
    }
}

El código de la clase "ProductoFresco":

Código: [Seleccionar]
public class ProductoFresco extends Producto{
    private String fechaEnvase;
    private String paisOrigen;
   
    public ProductoFresco(String fechaCaducidad, int numeroLote, String fechaEnvase, String paisOrigen){
        super(fechaCaducidad, numeroLote);
        this.fechaEnvase = fechaEnvase;
        this.paisOrigen = paisOrigen;
    }
   
    public void setFechaEnvase(String fechaEnvase){
        this.fechaEnvase = fechaEnvase;
    }
   
    public void setPaisOrigen(String paisOrigen){
        this.paisOrigen = paisOrigen;
    }
   
    public String getFechaEnvase(){return fechaEnvase;}
    public String getPaisOrigen(){return paisOrigen;}
   
    public void mostrarInfoProductoFresco(){
        System.out.println("El producto: "+getNumeroLote()+" con fecha de envase: "+getFechaEnvase()+" y fecha de caducidad: "+getFechaCaducidad()+" proviene de: "+getPaisOrigen());
    }
}

El código de la clase "ProductoRefrigerado":

Código: [Seleccionar]
public class ProductoRefrigerado extends ProductoFresco{
    private int codigoOrganismoSupervision;
    private float temperaturaMantenemientoRecom;
   
    public ProductoRefrigerado(String fechaCaducidad, int numeroLote, String fechaEnvase, String paisOrigen, float temperaturaMantenemientoRecom){
        super(fechaCaducidad, numeroLote, fechaEnvase, paisOrigen);
        this.temperaturaMantenemientoRecom = temperaturaMantenemientoRecom;
    }
   
    public ProductoRefrigerado(String fechaCaducidad, int numeroLote, String fechaEnvase, String paisOrigen, int codigoOrganismoSupervision, float temperaturaMantenemientoRecom){
        super(fechaCaducidad, numeroLote, fechaEnvase, paisOrigen);
        this.codigoOrganismoSupervision = codigoOrganismoSupervision;
        this.temperaturaMantenemientoRecom = temperaturaMantenemientoRecom;
    }
   
    public void setCodigoOrganismoSupervision(int codigoOrganismoSupervision){
        this.codigoOrganismoSupervision = codigoOrganismoSupervision;
    }
   
    public void setTemperaturaMantenemientoRecom(float temperaturaMantenemientoRecom){
        this.temperaturaMantenemientoRecom = temperaturaMantenemientoRecom;
    }
   
    public int getCodigoOrganismoSupervision(){return codigoOrganismoSupervision;}
    public float getTemperaturaMantenemientoRecom(){return temperaturaMantenemientoRecom;}
   
    public void mostrarInfoProductoRefrigerado(){
        System.out.println("El producto: "+getNumeroLote()+" con fecha de envase: "+getFechaEnvase()+" y fecha de caducidad: "+getFechaCaducidad()+" proviene de: "+getPaisOrigen()+". Tiene un código de Organismo de Supervisión: "+getCodigoOrganismoSupervision()+" y su temperatura de mantinemiento recomendada es de: "+getTemperaturaMantenemientoRecom()+"C");
    }
}

El código de la clase "ProductoCongelado":

Código: [Seleccionar]
public class ProductoCongelado extends ProductoRefrigerado{
   
    public ProductoCongelado(String fechaCaducidad, int numeroLote, String fechaEnvase, String paisOrigen, float temperaturaMantenemientoRecom){
        super(fechaCaducidad, numeroLote, fechaEnvase, paisOrigen, temperaturaMantenemientoRecom);
    }
   
    public void mostrarInfoProductoCongelado(){
        System.out.println("El producto: "+getNumeroLote()+" envasado en fecha: "+getFechaEnvase()+" y con fecha de caducidad: "+getFechaCaducidad()+" proviene de: "+getPaisOrigen()+" y tiene una temperatura de mantenemiento recomendad de: "+getTemperaturaMantenemientoRecom()+"C");
    }
}

El código de la clase "ProductoCongeladoPorAire":

Código: [Seleccionar]
public class ProductoCongeladoPorAire extends Producto{
    private float nitrogeno;
    private float oxigeno;
    private float co2;
    private float vaporAgua;
   
    public ProductoCongeladoPorAire(String fechaCaducidad, int numeroLote, float nitrogeno, float oxigeno, float co2, float vaporAgua){
        super(fechaCaducidad, numeroLote);
        this.nitrogeno = nitrogeno;
        this.oxigeno = oxigeno;
        this.co2 = co2;
        this.vaporAgua = vaporAgua;
    }
   
    public void setNitrogeno(float nitrogeno){
        this.nitrogeno = nitrogeno;
    }
   
    public void setOxigeno(float oxigeno){
        this.oxigeno = oxigeno;
    }
   
    public void setCo2(float co2){
        this.co2 = co2;
    }
   
    public void setVaporAgua(float vaporAgua){
        this.vaporAgua = vaporAgua;
    }
   
    public float getNitrogeno(){return nitrogeno;}
    public float getOxigeno(){return oxigeno;}
    public float getCo2(){return co2;}
    public float getVaporAgua(){return vaporAgua;}
   
    public void mostrarInfoProductoCongeladoPorAire(){
        System.out.println("El producto: "+getNumeroLote()+" con fecha de caducidad: "+getFechaCaducidad()+" tiene una composición de aire como sigue: ");
        System.out.println("Nitrógeno: "+getNitrogeno()+"%");
        System.out.println("Oxígeno: "+getOxigeno()+"%");
        System.out.println("Dióxido de carbono: "+getCo2()+"%");
        System.out.println("Vapor de agua: "+getVaporAgua()+"%");
    }
}

El código de la clase "ProductoCongeladoPorAgua":

Código: [Seleccionar]
public class ProductoCongeladoPorAgua extends Producto{
    private float salinidadAgua;
   
    public ProductoCongeladoPorAgua(String fechaCaducidad, int numeroLote, float salinidadAgua){
        super(fechaCaducidad, numeroLote);
        this.salinidadAgua = salinidadAgua;
    }
   
    public void setSalinidadAgua(float salinidadAgua){
        this.salinidadAgua = salinidadAgua;
    }
   
    public float getSalinidadAgua(){return salinidadAgua;}
   
    public void mostrarInfoProductoCongeladoPorAgua(){
        System.out.println("El producto: "+getNumeroLote()+" con fecha de caducidad: "+getFechaCaducidad()+" tiene un porcentaje de salinidad: "+getSalinidadAgua()+"gr sal por litro de agua");
    }
}

El código de la clase "ProductoCongeladoPorNitrogeno":

Código: [Seleccionar]
public class ProductoCongeladoPorNitrogeno extends Producto{
    private String metodoCongelacion;
    private int tiempoExposicion;
   
    public ProductoCongeladoPorNitrogeno(String fechaCaducidad, int numeroLote, String metodoCongelacion, int tiempoExposicion){
        super(fechaCaducidad, numeroLote);
        this.metodoCongelacion = metodoCongelacion;
        this.tiempoExposicion = tiempoExposicion;
    }
   
    public void setMetodoCongelacion(String metodoCongelacion){
        this.metodoCongelacion = metodoCongelacion;
    }
   
    public void setTiempoExposicion(int tiempoExposicion){
        this.tiempoExposicion = tiempoExposicion;
    }
   
    public String getMetodoCongelacion(){return metodoCongelacion;}
    public int getTiempoExposicion(){return tiempoExposicion;}
   
    public void mostrarInfoProductoCongeladoPorNitrogeno(){
        System.out.println("El producto: "+getNumeroLote()+" con fecha de caducidad: "+getFechaCaducidad()+" tuvo un método de congelación: "+getMetodoCongelacion()+" y estuvo expuesto al nitrógeno: "+getTiempoExposicion()+"s");
    }
}

El código de la clase main "TestHerencia3":

Código: [Seleccionar]
public class TestHerencia3{
    public static void main(String []Args){
        ProductoFresco productoFresco1 = new ProductoFresco("23-06-2016",1234, "05-01-2016","Argentina");
        ProductoFresco productoFresco2 = new ProductoFresco("22-06-2016",987,"09-10-2016","España");
        ProductoRefrigerado productoRefrigerado1 = new ProductoRefrigerado("10-10-2016",345,"01-03-2016","Ecuador",5);
        ProductoRefrigerado productoRefrigerado2 = new ProductoRefrigerado("11-10-2016",346,"02-03-2016","Colombia",5);
        ProductoRefrigerado productoRefrigerado3 = new ProductoRefrigerado("12-10-2016",347,"03-03-2016","Marruecos",5);
        ProductoCongeladoPorAgua productoCongeladoPorAgua1 = new ProductoCongeladoPorAgua("13-06-2016",908,40);
        ProductoCongeladoPorAgua productoCongeladoPorAgua2 = new ProductoCongeladoPorAgua("13-08-2016",988,35);
        ProductoCongeladoPorAire productoCongeladoPorAire1 = new ProductoCongeladoPorAire("11-08-2016",354,20,20,30,30);
        ProductoCongeladoPorAire productoCongeladoPorAire2 = new ProductoCongeladoPorAire("11-11-2016",428,10,20,30,40);
        ProductoCongeladoPorNitrogeno productoCongeladoPorNitrogeno1 = new ProductoCongeladoPorNitrogeno("10-08-2016",846,"Tradicional",200);
        productoFresco1.mostrarInfoProductoFresco();
        productoFresco2.mostrarInfoProductoFresco();
        productoRefrigerado1.mostrarInfoProductoRefrigerado();
        productoRefrigerado2.mostrarInfoProductoRefrigerado();
        productoRefrigerado3.mostrarInfoProductoRefrigerado();
        productoCongeladoPorAgua1.mostrarInfoProductoCongeladoPorAgua();
        productoCongeladoPorAgua2.mostrarInfoProductoCongeladoPorAgua();
        productoCongeladoPorAire1.mostrarInfoProductoCongeladoPorAire();
        productoCongeladoPorAire2.mostrarInfoProductoCongeladoPorAire();
        productoCongeladoPorNitrogeno1.mostrarInfoProductoCongeladoPorNitrogeno();
    }
}

Gracias.
« Última modificación: 14 de Marzo 2016, 11:26 por Mario R. Rancel »

Mario R. Rancel

  • Administrador
  • Experto
  • ********
  • APR2.COM
  • Mensajes: 1978
    • Ver Perfil
Buenos días

Has planteado unas relaciones de herencia muy extrañas, como si te hubieras equivocado de ejercicio

De la clases Producto deben heredar ProductoFresco, ProductoRefrigerado y ProductoCongelado.

De la clase ProductoCongelado deben heredar los distintos tipos de producto congelado.

En https://www.aprenderaprogramar.com/foros/index.php?topic=2342.0 tienes una propuesta de solución correcta y algunos comentarios

Revisa todo tu código

Saludos

Dimitar Stefanov

  • Experto
  • *****
  • Mensajes: 598
    • Ver Perfil
Buenas tardes, Mario.

Gracias por corregirme el ejercicio.

Creo que he entendido mal el ejercicio. Como el mismo indica:

Citar
Todos los productos llevan esta información común: fecha de caducidad y número de lote.

y:

Citar
Hay tres tipos de productos congelados: congelados por aire, congelados por agua y congelados por nitrógeno. Los productos congelados por aire deben llevar la información de la composición del aire con que fue congelado (% de nitrógeno, % de oxígeno, % de dióxido de carbono y % de vapor de agua). Los productos congelados por agua deben llevar la información de la salinidad del agua con que se realizó la congelación en gramos de sal por litro de agua. Los productos congelados por nitrógeno deben llevar la información del método de congelación empleado y del tiempo de exposición al nitrógeno expresada en segundos.

intepreté que los productos congelados por aire sólo tendrían que llevar la información: fecha de caducidad, número de lote y la composición del aire(nitrógeno, oxígeno, co2 y vapor de agua). Los productos congelados por agua tendrán que llevar la información: fecha de caducidad, número de lote y la salinidad. Y los productos congelados por nitrógeno: fecha de caducidad, número de lote y el tiempo de exposición al nitrógeno.

Por eso ví que lo más lógico era que todos los tipos de congelados por aire/agua/nitrógeno era más lógica que heredaran de la clase  "Producto" y no de la clase "ProductoCongelado". Aunque también debo decir que si un producto congelado por aire/agua/nitrógeno debería llevar la información de su padre "ProductoCongelado". Pero como también dije anteriormente, pensé que si dichos productos (ProductoCongeladoPorAire/Agua/Nitrogeno) tendrían que llevar la información de su padre lo hubieran puesto en el ejercicio. Sí, reconozco, este tema es más bien de lógica que no de leer el cometido del ejercicio.

Sobre el apartado b) del ejercicio:

Citar
b) Crear superclases intermedias (aunque no se correspondan con la descripción dada de la empresa) para agrupar atributos y métodos cuando sea posible. Esto corresponde a “realizar abstracciones” en el ámbito de la programación, que pueden o no corresponderse con el mundo real.

no ví la necesidad de crear ninguna superclase intermedia porque realmente la clase "Producto" lleva la información que necesitan las subclases "ProductoFresco", "ProductoRefrigerado" y "ProductoCongelado" y a su vez la subclase "ProductoFresco" lleva, en sí, la información que necesitan las subclases "ProductoRefrigerado" y "ProductoCongelado". Por último, la subclase "ProductoRefrigerado" lleva la información que necesita la subclase "ProductoCongelado" (aquí cabe un matíz que lo expongo más abajo).

 Así que, siguiendo esta lógica, sería de esperar que la subclase "ProductoCongelado" herede de la subclase "ProductoRefrigerados"(para la clase "ProductoCongelado" la clase "ProductoRefrigerado" es una superclase, pero para las clases con más nivel es una subclase). A su vez, la subclase "ProductoRefrigerado" herede de la subclase (su superclase) "ProductoFresco" y al final la subclase "ProductoFresco" herede de la superclase "Producto".

Sobre lo que había comentado antes que la subclase  "ProductoCongelado" conlleva la misma información que su superclase "ProductoRefrigerado" eso no es del todo cierto. En el anunciado del ejercicio se comenta:

Citar
Los productos refrigerados deben llevar el código del organismo de supervisión alimentaria, la fecha de envasado, la temperatura de mantenimiento recomendada y el país de origen. Los productos congelados deben llevar la fecha de envasado, el país de origen y la temperatura de mantenimiento recomendada.

vemos que la subclase "ProductoCongelado" lleva un campo menos que su superclase "ProductoRefrigerado". Ese "dilema" le he resuelto con un constructor sobreescrito en la subclase "ProductoRefrigerado" como podemos ver a continuación en el código de la subclase "ProductoRefrigerado":

Código: [Seleccionar]
public ProductoRefrigerado(String fechaCaducidad, int numeroLote, String fechaEnvase, String paisOrigen, float temperaturaMantenemientoRecom){
        super(fechaCaducidad, numeroLote, fechaEnvase, paisOrigen);
        this.temperaturaMantenemientoRecom = temperaturaMantenemientoRecom;
    }
   
    public ProductoRefrigerado(String fechaCaducidad, int numeroLote, String fechaEnvase, String paisOrigen, int codigoOrganismoSupervision, float temperaturaMantenemientoRecom){
        super(fechaCaducidad, numeroLote, fechaEnvase, paisOrigen);
        this.codigoOrganismoSupervision = codigoOrganismoSupervision;
        this.temperaturaMantenemientoRecom = temperaturaMantenemientoRecom;
    }

vemos que el primer constructor no lleva el parámetro "codigoOrganismoSupervision" cosa que nos brinda la oportunidad de crear un constructor adecuado con el cometido del ejercicio en la subclase "ProductoCongelado":

Código: [Seleccionar]
public ProductoCongelado(String fechaCaducidad, int numeroLote, String fechaEnvase, String paisOrigen, float temperaturaMantenemientoRecom){
        super(fechaCaducidad, numeroLote, fechaEnvase, paisOrigen, temperaturaMantenemientoRecom);
    }

Creo que con esta aclaración se explica la falta de una superclase "intermedia" de productos.

Adjunto el esquema como "esquemaCU00687B(011).jpg".

De todas maneras, considerando las anotaciones por parte de Mario R. Rancel deberíamos modificar los códigos de las subclases: "ProductoCongeladoPorAire", "ProductoCongeladoPorAgua", "ProductoCongeladoPorNitrogeno" y "TestHerencia3" que quedarían de la siguiente manera:

El código de la subclase "ProductoCongeladoPorAgua":

Código: [Seleccionar]
public class ProductoCongeladoPorAgua extends ProductoCongelado{
    private float salinidadAgua;
   
    public ProductoCongeladoPorAgua(String fechaCaducidad, int numeroLote, String fechaEnvase, String paisOrigen, float temperaturaMantenemientoRecom ,float salinidadAgua){
        super(fechaCaducidad, numeroLote, fechaEnvase, paisOrigen, temperaturaMantenemientoRecom);
        this.salinidadAgua = salinidadAgua;
    }
   
    public void setSalinidadAgua(float salinidadAgua){
        this.salinidadAgua = salinidadAgua;
    }
   
    public float getSalinidadAgua(){return salinidadAgua;}
   
    public void mostrarInfoProductoCongeladoPorAgua(){
        System.out.println("El producto: "+getNumeroLote()+" con fecha de caducidad: "+getFechaCaducidad()+" tiene un porcentaje de salinidad: "+getSalinidadAgua()+"gr sal por litro de agua");
    }
}

El código de la subclase "ProductoCongeladoPorAire":

Código: [Seleccionar]
public class ProductoCongeladoPorAire extends ProductoCongelado{
    private float nitrogeno;
    private float oxigeno;
    private float co2;
    private float vaporAgua;
   
    public ProductoCongeladoPorAire(String fechaCaducidad, int numeroLote,  String fechaEnvase, String paisOrigen, float temperaturaMantenemientoRecom, float nitrogeno, float oxigeno, float co2, float vaporAgua){
        super(fechaCaducidad, numeroLote, fechaEnvase, paisOrigen, temperaturaMantenemientoRecom);
        this.nitrogeno = nitrogeno;
        this.oxigeno = oxigeno;
        this.co2 = co2;
        this.vaporAgua = vaporAgua;
    }
   
    public void setNitrogeno(float nitrogeno){
        this.nitrogeno = nitrogeno;
    }
   
    public void setOxigeno(float oxigeno){
        this.oxigeno = oxigeno;
    }
   
    public void setCo2(float co2){
        this.co2 = co2;
    }
   
    public void setVaporAgua(float vaporAgua){
        this.vaporAgua = vaporAgua;
    }
   
    public float getNitrogeno(){return nitrogeno;}
    public float getOxigeno(){return oxigeno;}
    public float getCo2(){return co2;}
    public float getVaporAgua(){return vaporAgua;}
   
    public void mostrarInfoProductoCongeladoPorAire(){
        System.out.println("El producto: "+getNumeroLote()+" con fecha de caducidad: "+getFechaCaducidad()+" tiene una composición de aire como sigue: ");
        System.out.println("Nitrógeno: "+getNitrogeno()+"%");
        System.out.println("Oxígeno: "+getOxigeno()+"%");
        System.out.println("Dióxido de carbono: "+getCo2()+"%");
        System.out.println("Vapor de agua: "+getVaporAgua()+"%");
    }
}

El código de la subclase "ProductoCongeladoPorNitrogeno":

Código: [Seleccionar]
public class ProductoCongeladoPorNitrogeno extends ProductoCongelado{
    private String metodoCongelacion;
    private int tiempoExposicion;
   
    public ProductoCongeladoPorNitrogeno(String fechaCaducidad, int numeroLote, String fechaEnvase, String paisOrigen, float temperaturaMantenemientoRecom, String metodoCongelacion, int tiempoExposicion){
        super(fechaCaducidad, numeroLote, fechaEnvase, paisOrigen, temperaturaMantenemientoRecom);
        this.metodoCongelacion = metodoCongelacion;
        this.tiempoExposicion = tiempoExposicion;
    }
   
    public void setMetodoCongelacion(String metodoCongelacion){
        this.metodoCongelacion = metodoCongelacion;
    }
   
    public void setTiempoExposicion(int tiempoExposicion){
        this.tiempoExposicion = tiempoExposicion;
    }
   
    public String getMetodoCongelacion(){return metodoCongelacion;}
    public int getTiempoExposicion(){return tiempoExposicion;}
   
    public void mostrarInfoProductoCongeladoPorNitrogeno(){
        System.out.println("El producto: "+getNumeroLote()+" con fecha de caducidad: "+getFechaCaducidad()+" tuvo un método de congelación: "+getMetodoCongelacion()+" y estuvo expuesto al nitrógeno: "+getTiempoExposicion()+"s");
    }
}

Y el código de la clase main "TestHerencia3":

Código: [Seleccionar]
public class TestHerencia3{
    public static void main(String []Args){
        ProductoFresco productoFresco1 = new ProductoFresco("23-06-2016",1234, "05-01-2016","Argentina");
        ProductoFresco productoFresco2 = new ProductoFresco("22-06-2016",987,"09-10-2016","España");
        ProductoRefrigerado productoRefrigerado1 = new ProductoRefrigerado("10-10-2016",345,"01-03-2016","Ecuador",5);
        ProductoRefrigerado productoRefrigerado2 = new ProductoRefrigerado("11-10-2016",346,"02-03-2016","Colombia",5);
        ProductoRefrigerado productoRefrigerado3 = new ProductoRefrigerado("12-10-2016",347,"03-03-2016","Marruecos",5);
        ProductoCongeladoPorAgua productoCongeladoPorAgua1 = new ProductoCongeladoPorAgua("13-06-2016",908,"12-05-2016","Estados Unidos",-21,40);
        ProductoCongeladoPorAgua productoCongeladoPorAgua2 = new ProductoCongeladoPorAgua("13-08-2016",988,"13-05-2016","Francia",-18,35);
        ProductoCongeladoPorAire productoCongeladoPorAire1 = new ProductoCongeladoPorAire("11-08-2016",354,"11-05-2016","Alemania",-19,20,20,30,30);
        ProductoCongeladoPorAire productoCongeladoPorAire2 = new ProductoCongeladoPorAire("11-11-2016",428,"08-08-2016","Países Bajos",-15,10,20,30,40);
        ProductoCongeladoPorNitrogeno productoCongeladoPorNitrogeno1 = new ProductoCongeladoPorNitrogeno("10-08-2016",846,"08-06-2016","Bolivia",-22,"Tradicional",200);
        productoFresco1.mostrarInfoProductoFresco();
        productoFresco2.mostrarInfoProductoFresco();
        productoRefrigerado1.mostrarInfoProductoRefrigerado();
        productoRefrigerado2.mostrarInfoProductoRefrigerado();
        productoRefrigerado3.mostrarInfoProductoRefrigerado();
        productoCongeladoPorAgua1.mostrarInfoProductoCongeladoPorAgua();
        productoCongeladoPorAgua2.mostrarInfoProductoCongeladoPorAgua();
        productoCongeladoPorAire1.mostrarInfoProductoCongeladoPorAire();
        productoCongeladoPorAire2.mostrarInfoProductoCongeladoPorAire();
        productoCongeladoPorNitrogeno1.mostrarInfoProductoCongeladoPorNitrogeno();
    }
}

Adjunto el esquema de la modificación del ejercicio como "esquemaCU00687B(022)".

No sé si con esta constestación he resuelto el ejercicio y he comprendido mejor el mismo.

Gracias
« Última modificación: 16 de Marzo 2016, 21:03 por Mario R. Rancel »

Mario R. Rancel

  • Administrador
  • Experto
  • ********
  • APR2.COM
  • Mensajes: 1978
    • Ver Perfil
Buenas tardes

Has citado algo importante: tienes que guardar la lógica en los diseños. En determinadas situaciones puedes encontrar soluciones que suponen atajos pero que contravienen la lógica. Esto a la larga genera inconsistencias y hace que los programas terminen por fallar.

Por criterio de lógica, un producto congelado no debe heredar de un producto refrigerado: no tiene lógica (incluso aunque en un caso concreto puedas cuadrarlo así sería algo contrario a la lógica).

Tienes que hacer un diseño coherente: public class ProductoRefrigerado extends ProductoFresco no es coherente. Un ProductoRefrigerado no es un tipo de ProductoFresco. Supón que tienes la clase Fruta y las clases FrutaDulce, FrutaAmarga y FrutaMixta. No tendría ningún sentido decir que FrutaAmarga hereda de FrutaDulce. El diseño coherente sería que Fruta sea superclase de FrutaDulce, FrutaAmarga y FrutaMixta. Independientemente de cómo se organicen luego los atributos. Lo primero será tener un diseño coherente. El diseño que muestras no es coherente.

En el hilo https://www.aprenderaprogramar.com/foros/index.php?topic=2342.0 tienes un diseño consistente: el esquema planteado es lógico.

Saludos

Dimitar Stefanov

  • Experto
  • *****
  • Mensajes: 598
    • Ver Perfil
Hola, Mario.

Ah, ahora entendí a lo que te refieres. Vale.

Voy a corregir este ejercicio y el siguiente (CU00688B) que ya lo he colgado, pero viendo esto sé que lo tengo mal planteado. Voy a corregir los dos y subire las correcciones. 

Gracias por ayudarme.

Saludos.

Dimitar Stefanov

  • Experto
  • *****
  • Mensajes: 598
    • Ver Perfil
Hola, de nuevo, Mario :)

Espero que esta vez sea la vencida y tenga todo bien (lógica y códigos).

A continuación procederé en subir todos los códigos de las clases:

Clase "Producto":

Código: [Seleccionar]
public class Producto{
    private String fechaCaducidad;
    private int numeroLote;
    private String fechaEnvase;
    private String paisOrigen;
   
    public Producto(String fechaCaducidad, int numeroLote, String fechaEnvase, String paisOrigen){
        this.fechaCaducidad = fechaCaducidad;
        this.numeroLote = numeroLote;
        this.fechaEnvase = fechaEnvase;
        this.paisOrigen = paisOrigen;
    }
   
    public void setFechaCaducidad(String fechaCaducidad){
        this.fechaCaducidad = fechaCaducidad;
    }
   
    public void setNumeroLote(int numeroLote){
        this.numeroLote = numeroLote;
    }
   
    public void setFechaEnvase(String fechaEnvase){
        this.fechaEnvase = fechaEnvase;
    }
   
    public void setPaisOrigen(String paisOrigen){
        this.paisOrigen = paisOrigen;
    }
   
    public String getFechaCaducidad(){return fechaCaducidad;}
    public int getNumeroLote(){return numeroLote;}
    public String getFechaEnvase(){return fechaEnvase;}
    public String getPaisOrigen(){return paisOrigen;}
   
    public void mostrarInfoProducto(){
        System.out.println("El producto: "+getNumeroLote()+" tiene una fecha de caducidad: "+getFechaCaducidad());
    }
}

Clase "ProductoFresco":

Código: [Seleccionar]
public class ProductoFresco extends Producto{
   
    public ProductoFresco(String fechaCaducidad, int numeroLote, String fechaEnvase, String paisOrigen){
        super(fechaCaducidad, numeroLote, fechaEnvase, paisOrigen);
    }
   
    public void mostrarInfoProductoFresco(){
        System.out.println("El producto Fresco: "+getNumeroLote()+" con fecha de envase: "+getFechaEnvase()+" y fecha de caducidad: "+getFechaCaducidad()+" proviene de: "+getPaisOrigen());
    }
}

Clase "ProductoRefrigeradoYCongelado" (hacía falsta de una clase "intermedia", jeje):

Código: [Seleccionar]
public class ProductoRefrigeradoYCongelado extends Producto{
    private float temperaturaMantenemientoRecom;
   
    public ProductoRefrigeradoYCongelado(String fechaCaducidad, int numeroLote, String fechaEnvase, String paisOrigen, float temperaturaMantenemientoRecom){
        super(fechaCaducidad, numeroLote, fechaEnvase, paisOrigen);
        this.temperaturaMantenemientoRecom = temperaturaMantenemientoRecom;
    }
   
    public void setTemperaturaMantenemientoRecom(float temperaturaMantenemientoRecom){
        this.temperaturaMantenemientoRecom = temperaturaMantenemientoRecom;
    }

    public float getTemperaturaMantenemientoRecom(){return temperaturaMantenemientoRecom;}
   
    public void mostrarInfoProductoRefrigeradoYCongelado(){
        System.out.print("El producto Refrigerado/Congelado: "+getNumeroLote()+" envasado en fecha: "+getFechaEnvase()+" y con fecha de caducidad: "+getFechaCaducidad()+" proviene de: "+getPaisOrigen()+", tiene una temperatura de mantenemiento recomendad de: "+getTemperaturaMantenemientoRecom()+"C");
    }
}

Clase "ProductoRefrigerado":

Código: [Seleccionar]
public class ProductoRefrigerado extends ProductoRefrigeradoYCongelado{
    private int codigoOrganismoSupervision;
   
    public ProductoRefrigerado(String fechaCaducidad, int numeroLote, String fechaEnvase,  String paisOrigen, float temperaturaMantenemientoRecom, int codigoOrganismoSupervision){
        super(fechaCaducidad, numeroLote, fechaEnvase, paisOrigen, temperaturaMantenemientoRecom);
        this.codigoOrganismoSupervision = codigoOrganismoSupervision;
    }
   
    public void setCodigoOrganismoSupervision(int codigoOrganismoSupervision){
        this.codigoOrganismoSupervision = codigoOrganismoSupervision;
    }
   
    public int getCodigoOrganismoSupervision(){return codigoOrganismoSupervision;}
   
    public void mostrarInfoProductoRefrigerado(){
        mostrarInfoProductoRefrigeradoYCongelado();
        System.out.print(" y un código de Organismo de Supervisión: "+getCodigoOrganismoSupervision()+"\n");
    }
}

Clase "ProductoCongelado":

Código: [Seleccionar]
public class ProductoCongelado extends ProductoRefrigeradoYCongelado{
   
    public ProductoCongelado(String fechaCaducidad, int numeroLote, String fechaEnvase, String paisOrigen, float temperaturaMantenemientoRecom){
        super(fechaCaducidad, numeroLote, fechaEnvase, paisOrigen, temperaturaMantenemientoRecom);
    }
   
    public void mostrarInfoProductoCongelado(){
        mostrarInfoProductoRefrigeradoYCongelado();
        System.out.println();
    }
}

Clase "ProductoCongeladoPorAire":

Código: [Seleccionar]
public class ProductoCongeladoPorAire extends ProductoCongelado{
    private float nitrogeno;
    private float oxigeno;
    private float co2;
    private float vaporAgua;
   
    public ProductoCongeladoPorAire(String fechaCaducidad, int numeroLote,  String fechaEnvase, String paisOrigen, float temperaturaMantenemientoRecom, float nitrogeno, float oxigeno, float co2, float vaporAgua){
        super(fechaCaducidad, numeroLote, fechaEnvase, paisOrigen, temperaturaMantenemientoRecom);
        this.nitrogeno = nitrogeno;
        this.oxigeno = oxigeno;
        this.co2 = co2;
        this.vaporAgua = vaporAgua;
    }
   
    public void setNitrogeno(float nitrogeno){
        this.nitrogeno = nitrogeno;
    }
   
    public void setOxigeno(float oxigeno){
        this.oxigeno = oxigeno;
    }
   
    public void setCo2(float co2){
        this.co2 = co2;
    }
   
    public void setVaporAgua(float vaporAgua){
        this.vaporAgua = vaporAgua;
    }
   
    public float getNitrogeno(){return nitrogeno;}
    public float getOxigeno(){return oxigeno;}
    public float getCo2(){return co2;}
    public float getVaporAgua(){return vaporAgua;}
   
    public void mostrarInfoProductoCongeladoPorAire(){
        mostrarInfoProductoRefrigeradoYCongelado();
        System.out.print(" y tiene una composición de aire como sigue: ");
        System.out.println("Nitrógeno: "+getNitrogeno()+"%");
        System.out.println("Oxígeno: "+getOxigeno()+"%");
        System.out.println("Dióxido de carbono: "+getCo2()+"%");
        System.out.println("Vapor de agua: "+getVaporAgua()+"%");
    }
}

Clase "ProductoCongeladoPorAgua":

Código: [Seleccionar]
public class ProductoCongeladoPorAgua extends ProductoCongelado{
    private float salinidadAgua;
   
    public ProductoCongeladoPorAgua(String fechaCaducidad, int numeroLote, String fechaEnvase, String paisOrigen, float temperaturaMantenemientoRecom ,float salinidadAgua){
        super(fechaCaducidad, numeroLote, fechaEnvase, paisOrigen, temperaturaMantenemientoRecom);
        this.salinidadAgua = salinidadAgua;
    }
   
    public void setSalinidadAgua(float salinidadAgua){
        this.salinidadAgua = salinidadAgua;
    }
   
    public float getSalinidadAgua(){return salinidadAgua;}
   
    public void mostrarInfoProductoCongeladoPorAgua(){
        mostrarInfoProductoRefrigeradoYCongelado();
        System.out.print(" y tiene un porcentaje de salinidad: "+getSalinidadAgua()+"gr sal por litro de agua\n");
    }
}

Clase "ProductoCongeladoPorNitrogeno":

Código: [Seleccionar]
public class ProductoCongeladoPorNitrogeno extends ProductoCongelado{
    private String metodoCongelacion;
    private int tiempoExposicion;
   
    public ProductoCongeladoPorNitrogeno(String fechaCaducidad, int numeroLote, String fechaEnvase, String paisOrigen, float temperaturaMantenemientoRecom, String metodoCongelacion, int tiempoExposicion){
        super(fechaCaducidad, numeroLote, fechaEnvase, paisOrigen, temperaturaMantenemientoRecom);
        this.metodoCongelacion = metodoCongelacion;
        this.tiempoExposicion = tiempoExposicion;
    }
   
    public void setMetodoCongelacion(String metodoCongelacion){
        this.metodoCongelacion = metodoCongelacion;
    }
   
    public void setTiempoExposicion(int tiempoExposicion){
        this.tiempoExposicion = tiempoExposicion;
    }
   
    public String getMetodoCongelacion(){return metodoCongelacion;}
    public int getTiempoExposicion(){return tiempoExposicion;}
   
    public void mostrarInfoProductoCongeladoPorNitrogeno(){
        mostrarInfoProductoRefrigeradoYCongelado();
        System.out.print(" y tuvo un método de congelación: "+getMetodoCongelacion()+" y estuvo expuesto al nitrógeno: "+getTiempoExposicion()+"s\n");
    }
}

Clase "TestHerencia3":

Código: [Seleccionar]
public class TestHerencia3{
    public static void main(String []Args){
        ProductoFresco productoFresco1 = new ProductoFresco("23-06-2016",1234, "05-01-2016","Argentina");
        ProductoFresco productoFresco2 = new ProductoFresco("22-06-2016",987,"09-10-2016","España");
        ProductoRefrigerado productoRefrigerado1 = new ProductoRefrigerado("10-10-2016",345,"01-03-2016","Ecuador",5,455);
        ProductoRefrigerado productoRefrigerado2 = new ProductoRefrigerado("11-10-2016",346,"02-03-2016","Colombia",6,8495);
        ProductoRefrigerado productoRefrigerado3 = new ProductoRefrigerado("12-10-2016",347,"03-03-2016","Marruecos",4,2345);
        ProductoCongeladoPorAgua productoCongeladoPorAgua1 = new ProductoCongeladoPorAgua("13-06-2016",908,"12-05-2016","Estados Unidos",-21,40);
        ProductoCongeladoPorAgua productoCongeladoPorAgua2 = new ProductoCongeladoPorAgua("13-08-2016",988,"13-05-2016","Francia",-18,35);
        ProductoCongeladoPorAire productoCongeladoPorAire1 = new ProductoCongeladoPorAire("11-08-2016",354,"11-05-2016","Alemania",-19,20,20,30,30);
        ProductoCongeladoPorAire productoCongeladoPorAire2 = new ProductoCongeladoPorAire("11-11-2016",428,"08-08-2016","Países Bajos",-15,10,20,30,40);
        ProductoCongeladoPorNitrogeno productoCongeladoPorNitrogeno1 = new ProductoCongeladoPorNitrogeno("10-08-2016",846,"08-06-2016","Bolivia",-22,"Tradicional",200);
        productoFresco1.mostrarInfoProductoFresco();
        productoFresco2.mostrarInfoProductoFresco();
        productoRefrigerado1.mostrarInfoProductoRefrigerado();
        productoRefrigerado2.mostrarInfoProductoRefrigerado();
        productoRefrigerado3.mostrarInfoProductoRefrigerado();
        productoCongeladoPorAgua1.mostrarInfoProductoCongeladoPorAgua();
        productoCongeladoPorAgua2.mostrarInfoProductoCongeladoPorAgua();
        productoCongeladoPorAire1.mostrarInfoProductoCongeladoPorAire();
        productoCongeladoPorAire2.mostrarInfoProductoCongeladoPorAire();
        productoCongeladoPorNitrogeno1.mostrarInfoProductoCongeladoPorNitrogeno();
    }
}

Y adjunto la foto del esquema.

Mario, el hilo que me diste y el ejercicio de "arcanFAC" son una pasada. En su ejercicio se va incluso más allá de lo que pide el ejercicio y con su código puedes entrar tu (por consola) los datos de cada objeto e imprimirlos posteriormente. Le felicito! Yo eso no lo he hecho, primero quería ver si voy bien encaminado.

Gracias

Mario R. Rancel

  • Administrador
  • Experto
  • ********
  • APR2.COM
  • Mensajes: 1978
    • Ver Perfil
Buenas tardes

Ahora sí, puedes dar el ejercicio por correcto, código y lógica. Comentaré algunas cosas, pero no creo que debas seguir revisando este ejercicio sino seguir avanzando.

Hay algunos detalles interesantes. Por ejemplo el enunciado dice: "Todos los productos llevan esta información común: fecha de caducidad y número de lote. A su vez, cada tipo de producto lleva alguna información específica. Los productos frescos deben llevar la fecha de envasado y el país de origen. Los productos refrigerados deben llevar el código del organismo de supervisión alimentaria, la fecha de envasado, la temperatura de mantenimiento recomendada y el país de origen. Los productos congelados deben llevar la fecha de envasado, el país de origen y la temperatura de mantenimiento recomendada."

Aquí parece haber un error en el enunciado, porque nos dice que la información común de los productos es fecha de caducidad y número de lote. Sin embargo por la explicación vemos que hay más información común. ¿Error? Hay que tener en cuenta que cuando un cliente hace el encargo de un programa nos puede proporcionar información mal especificada o con contradicciones. Por ello como programadores habremos de encargarnos de:

a) Entender bien el problema
b) Solicitar aclaraciones si son necesarias
c) Reestructurar la información y el código cuando lo consideremos conveniente

En este caso de la explicación se deduce que es conveniente agrupar los atributos "fecha de envasado" y "país de origen" para evitar su repetición en las subclases.


Sobre la clase "ProductoRefrigeradoYCongelado" ¿hacía falta una clase "intermedia"? Digamos que hacía falta porque el ejercicio así lo pedía. Esta clase supone desviar el diseño en código del esquema del problema en el mundo real. Es decir, en el mundo real no existe un tipo de producto refrigerado-congelado. No obstante, nosotros como programadores podemos crear este tipo de abstracciones cuando lo consideremos oportuno. Pero siempre guardando coherencia. En este caso es coherente que de Producto herede ProductoRefrigerado-Congelado y que de ahí continue la herencia. Creo que hubiera sido más apropiado el nombre ProductoRefrigeradoOCongelado en lugar de YCongelado porque esta clase representa una abstracción de un producto refrigerado ó congelado, no de ambas cosas al mismo tiempo.

En este fragmento de código hay una idea interesante:

Código: [Seleccionar]
    public void mostrarInfoProductoRefrigerado(){
        mostrarInfoProductoRefrigeradoYCongelado();
        System.out.print(" y un código de Organismo de Supervisión: "+getCodigoOrganismoSupervision()+"\n");
    }

La idea es reutilizar el código de superclases para evitar su repetición en las subclases. Buena idea. Más adelante en el curso se ve cómo sofisticar aún más esta idea.

La pregunta es: ¿Por qué no hiciste lo mismo en todos los casos? Por ejemplo que el método public void mostrarInfoProductoFresco() reutilizara mostrarInfoProducto de la clase Producto?

La idea del polimorfismo tienes que ir asentándola poco a poco. Para ello te propongo esta reflexión:

Si escribes ProductoFresco productoFresco1 = new ProductoFresco("23-06-2016",1234, "05-01-2016","Argentina"); entonces productoFresco1 es solamente de un tipo, es de tipo ProductoFresco.

Si escribes Producto productoFresco1 = new ProductoFresco("23-06-2016",1234, "05-01-2016","Argentina"); entonces productoFresco1 es de dos tipos: es de tipo Producto (tipo estático) y de tipo ProductoFresco (tipo dinámico).

Saludos

Dimitar Stefanov

  • Experto
  • *****
  • Mensajes: 598
    • Ver Perfil
Buenas tardes, Mario.

Gracias por revisar el ejercicio (otra vez más :)) y comentar hasta el último detalle, jeje.

Me alegro que, por fin, podemos dar este ejercicio como "bueno" :)

Sí, sobre la reutilización de información ya entrada en el programa tienes razón. Debería haber utilizado más lo que estaba en las superclases para no repetir tanto código en las subclases.

Sobre lo de cuando declaro una variable como estática y luego su declaración dinámica, sí, con los ejercicios vinientes me aclaro más las ideas.

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