Autor Tema: Ejemplo implementar interface Iterable sobre una clase Java CU00688B  (Leído 4681 veces)

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 989
    • Ver Perfil
Hola, a ver quien me puede echar una mano.

Estoy con este ejercicio:

Citar
Amplía el código del programa Java que planteamos como ejercicio en la entrega CU00687 de este curso, relativo a la gestión de una empresa agroalimentaria, teniendo en cuenta que la empresa gestiona envíos a través de diferentes medios, y un envío puede contener cierto número de productos frescos, refrigerados o congelados. Añade al código:

a) Una clase EnvioDeProductos que represente un envío de productos como colección de objetos que admite el polimorfismo.

b) Crear una clase testHerencia4 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). Crear un envío que represente la agrupación de los anteriores productos. Mostrar por pantalla la información del número de productos que componen el envío y recorrer los productos del envío usando iterator para mostrar la información (valor de los atributos) de cada uno de ellos.

Bien, esta de abajo es mi clase EnvioDeProductos. Se deja compilar y funciona correctamente.
El último método, listarEnvio(), lo escribí y lo dejé escrito ya sabiendo que no iba a servir para lo que propone el ejercicio, ya que lo único que hace es mostrar los nombres de los objetos incorporados en el ArrayList, pero no sus atributos.
Aquí el método iterator() si funciona. (luego veréis porque hago este apunte)

Código: [Seleccionar]
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;

/**
 * Clase para definir envios de productos mediante una colección polimórfica.
 *
 * @author Kabuto
 * @version 1.0
 */
public class EnvioDeProductos{
   
    private List<Producto> envioProductos;
   
    public EnvioDeProductos(){
        envioProductos = new ArrayList<Producto>();
    }
   
    //Método para obtener un determinado producto pasando un indice como parámetro
    public Producto getEnvioDeProductos(int i){return envioProductos.get(i);}
   
    //Método para modificar un produto de la lista indicando el producto y un indice
    public void setEnvioDeProductos(Producto nombreProducto, int i){envioProductos.add(i, nombreProducto);}
   
    //Método para añadir nuevos productos a la lista
    public void addEnvioDeProductos(Producto nombreProducto){envioProductos.add(nombreProducto);}
   
    //Para consultar cuantos objetos componen la lista
    public int longitudLista(){return envioProductos.size();}
   
    /*Método para listar los productos del envío.
     *Tan solo muestra el nombre de cada objeto, no sus atributos
     */
    public void listarEnvio(){
        Iterator<Producto> it = envioProductos.iterator();
        Producto producTmp;
        while (it.hasNext()) {
            producTmp = it.next();
            System.out.println(producTmp);
        }
    }
}

Bien, ahora viene el main donde creo los distintos productos y los meto juntitos en el ArrayList de EnvioDeProducto.
Todo este proceso furula correctamente.
Al final pretendo hacer lo que propone el ejercicio: Recorrer los productos con un iterador y mostrar toda la información de cada producto.

Pero aquí es donde me da un error al compilar. Me dice que no puedo aplicarle el método iterator() a nuevoEnvio, que es el objeto de la clase GestionDeEnvios, vamos un ArrayList.
¿Por qué aquí no me permite aplicárselo y sin embargo si puedo hacerlo en el código que define la clase?

Os adjunto un zip con todas las clases que componen el proyecto

Código: [Seleccionar]
import java.util.Calendar;
import java.util.Iterator;

/**
 * Programa para testear la creacion de productos con herencias
 * dos productos frescos, tres productos refrigerados y cinco productos congelados (2 de ellos congelados
 * por aire, otros 2 por agua y 1 por nitrógeno). Crear un envio y mostrar datos.
 *
 * @author Kabuto
 * @version 1.0
 */
public class TestEnvioProducto {
    public static void main (String[] args){
        Calendar fechaCaducidad = Calendar.getInstance();
        Calendar fechaEnvasado = Calendar.getInstance();
       
        fechaCaducidad.set(2015,11,25);
        fechaEnvasado.set(2015,5,25);//Por comodidad pasaremos las mismas fechas a todos los contructores.
       
        //Creamos varios productos
        Fresco fresco1 = new Fresco(fechaCaducidad, fechaEnvasado, "España", 224);
        Fresco fresco2 = new Fresco(fechaCaducidad, fechaEnvasado, "España", 227);
       
        Refrigerado refri1 = new Refrigerado(fechaCaducidad, fechaEnvasado, "Alemania", 124);
        refri1.setCodigoSuperVision(123); refri1.setTemperaturaConservacion(20);
        Refrigerado refri2 = new Refrigerado(fechaCaducidad, fechaEnvasado, "Brasil", 132);
        refri2.setCodigoSuperVision(120); refri2.setTemperaturaConservacion(18);
        Refrigerado refri3 = new Refrigerado(fechaCaducidad, fechaEnvasado, "China", 114);
        refri3.setCodigoSuperVision(113); refri1.setTemperaturaConservacion(21);
       
        Aire congeladoAire1 = new Aire(fechaCaducidad, fechaEnvasado, "EEUU", 285);
        congeladoAire1.setComposicionAire(25, 25, 25, 25);
        Aire congeladoAire2 = new Aire(fechaCaducidad, fechaEnvasado, "Perú", 034);
        congeladoAire1.setComposicionAire(20, 10, 30, 40);
       
        Agua congeladoAgua1 = new Agua (fechaCaducidad, fechaEnvasado, "España", 112);
        congeladoAgua1.setSalinidad(12);
        Agua congeladoAgua2 = new Agua (fechaCaducidad, fechaEnvasado, "Japón", 123);
        congeladoAgua2.setSalinidad(18);
       
        Nitrogeno congeladoNitrogeno = new Nitrogeno(fechaCaducidad, fechaEnvasado, "Rusia", 155);
        congeladoNitrogeno.setMetodoCongelacion("Soplando muy fuerte");
        congeladoNitrogeno.setTiempoExposicion(500);
       
        //Creamos un envio con todos estosproductos
        EnvioDeProductos nuevoEnvio = new EnvioDeProductos();
        nuevoEnvio.addEnvioDeProductos(fresco1); nuevoEnvio.addEnvioDeProductos(fresco2);
        nuevoEnvio.addEnvioDeProductos(refri1);nuevoEnvio.addEnvioDeProductos(refri2);nuevoEnvio.addEnvioDeProductos(refri3);
        nuevoEnvio.addEnvioDeProductos(congeladoAire1);nuevoEnvio.addEnvioDeProductos(congeladoAire2);
        nuevoEnvio.addEnvioDeProductos(congeladoAgua1);nuevoEnvio.addEnvioDeProductos(congeladoAgua2);
        nuevoEnvio.addEnvioDeProductos(congeladoNitrogeno);
       
        //Mostramos el número de productos en el envío
        System.out.println("El envío está compuesto por " + nuevoEnvio.longitudLista() + " productos.");
        System.out.println("Listado de productos actuales");
        System.out.println("-----------------------------");
        System.out.println("");
               
        //Mostramos los datos de los productos a enviar
        Iterator<Producto> it = nuevoEnvio.iterator();//Iterator da error "cannot find symbol method .iterator()
        Producto producTmp;
        while (it.hasNext()) {
            producTmp = it.next();
            producTmp.mostrarDatos();
        }
    }
}
« Última modificación: 15 de Abril 2015, 11:09 por Alex Rodríguez »
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
Ok. Ya lo he resuelto.

Para poder iterar con la clase EnvioDeProductos he tenido que implementarle la interfaz Iterable, definiendo la clase del siguiente modo:
Código: [Seleccionar]
public class EnvioDeProductos  implements Iterable<Producto>{
Esto me solucionó el problema a la hora de iterar, pero entonces apareció uno nuevo.

Al iterar cada objeto, yo pretendía mostrar sus datos llamando al método .mostrarDatos().

Código: [Seleccionar]
while (it.hasNext()) {
            producTmp = it.next();
            producTmp.mostrarDatos();

Este método está definido en cada una de las subclases y es distinto para cada una, pues cada subclase tiene atributos propios.

Si applicaba este método directamente sobre los objetos creados, por ejemplo refri1.mostrarDatos(), si que funcionaba y mostraba los datos correspondientes para cada subclase.
Pero no servía para el objeto temporal producTmp, ya que este objeto es de la clase Producto (la superclase), la cuál no tiene ningún metodo .mostrarDatos().

Lo he solucionado declarando la clase Producto como abstracta y añadiéndole un método .mostrarDatos() abstracto, sin nada de código:

Código: [Seleccionar]
public abstract class Producto {
   ...
   ...
   public abstract void mostrarDatos();
}

Y después en cada subclase donde tengo este método lo modifico con la anotación @override para que sobreescriba al método abstracto de la superclase.

Por ejemplo:
Código: [Seleccionar]
@Override
    public void mostrarDatos(){
        System.out.println("Fecha de caducidad: " + getFechaCaducidad().getTime().toString());
        System.out.println("Fecha de Envasado: " + getFechaEnvasado().getTime().toString());
        System.out.println("País de origen: " + getPaisOrigen());
        System.out.println("Número de Lote: " + getNumeroLote());
        System.out.println("Temperatura de mantenimiento: " + getTempMantenimiento());
    }


 ;D De este modo, ahora si consigo iterar sin problemas y puedo llamar al método .mostrarDatos() ejecutándose el que corresponde a cada clase según el objeto al que estemos iterando.
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

Alex Rodríguez

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 2050
    • Ver Perfil
Hola Kabuto, investigar y probar soluciones es bueno pues nos da mayor dominio de la programación. En el código que te fallaba tenías esto:

EnvioDeProductos nuevoEnvio = new EnvioDeProductos();

Iterator<Producto> it = nuevoEnvio.iterator();


Pero no te permitía iterar sobre un objeto nuevoEnvio... porque este objeto no permitía obtener iteradores.

Sin embargo un envío contenía un arrayList que sí permite obtener iteradores.

Si en el código de EnvioDeProductos introducimos:

    public ArrayList<Producto> getEnvio(){ return envioProductos;}

con esto ya podemos recuperar el ArrayList que sí permite obtener un iterador.

Luego en la clase TestEnvioProducto puedes recuperar el ArrayList:

Iterator<Producto> it = nuevoEnvio.getEnvio().iterator();

Todavía tendrías que hacer algunas correcciones, pero con esa idea creo que podrías conseguir que el código inicial funcionara.

Saludos

Kabuto

  • Moderador Global
  • Experto
  • *******
  • Mensajes: 989
    • Ver Perfil
Re:Ejemplo implementar interface Iterable sobre una clase Java CU00688B
« Respuesta #3 en: 15 de Abril 2015, 14:12 »
Humm.. probaré del modo que dices.

Muchas gracias Alex  ;)
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".