How does a construction Collection<Interface> work in Java?

80 Views Asked by At

I had encountered a problem. There are a class and an interface:

Class:

public class Food implements NutritionalElement {
    private String name;
    private double calories;
    private double proteins;
    private double carbs;
    private double fat;
    private HashMap<String, ArrayList<Double>> rawMaterialsList = new HashMap<String, ArrayList<Double>>();

    public void defineRawMaterial(String name,
                                      double calories,
                                      double proteins,
                                      double carbs,
                                      double fat){
        this.name = name;
        this.calories = calories;
        this.proteins = proteins;
        this.carbs = carbs;
        this.fat = fat;
        ArrayList<Double> nutrision = new ArrayList<>();
        nutrision.add(this.calories);
        nutrision.add(this.proteins);
        nutrision.add(this.carbs);
        nutrision.add(this.fat);
        rawMaterialsList.put(this.name, nutrision);
    }
    
    /**
     * Retrieves the collection of all defined raw materials
     * @return collection of raw materials through the {@link NutritionalElement} interface 
     * problem is here      
     */
    public Collection<NutritionalElement> rawMaterials(){
    
        
        return res;
    }

And an interface:

package diet;



public interface NutritionalElement {
    public String getName();
    
    public double getCalories();


    public double getProteins();
    

    public double getCarbs();


    public double getFat();


    public boolean per100g();
}

The program is large and that actually makes sense. I just included a tiny part of the whole project.

And I am completely lost, I have never met something like that. I would ask to help me understand how I should complete the method in the class. Thank you.

EDIT: I don't understand how to implement this method:

public Collection<NutritionalElement> rawMaterials(){}

Should it return a collection of interfaces or what? By the way, this is university project and the method should be implemented in the same manner as it was provided by the professor (I cannot change return type at all). Sorry for bad explanation at the beginning.

4

There are 4 best solutions below

1
Chaosfire On BEST ANSWER

Going by common sense, your structure is incorrect. The nutritional elements are carbs, fats, proteins, probably other stuff I am not aware of. It seems you should have classes representing each of those elements.

class Carbohydrates implements NutritionalElement {
  //implement the methods
}

Create similar classes for the other elements.

Then Food should look like:

class Food {

  private List<NutritionalElement> elements;
  
  //constructors

  //other methods, if necesarry

  public Collection<NutritionalElement> rawMaterials(){  
    return this.elements;
  }
}

The food is not a NutritionalElement, but it has many NutritionalElements.

Tbh it seems the interface also needs refactoring, because carbohydrates having methods to get fats and proteins seems strange.

0
Lajos Arpad On

This is a very frequently used pattern.

An interface declares a pattern of classes, declaring what they should be able to execute, via method names, parameter specification and return type, without actually caring about the actual implementation.

It is your job to implement classes that will implement the interface and to do the instantiation. Read more about that part here: https://docs.oracle.com/javase/tutorial/java/IandI/usinginterface.html

However, at the space of your method of

public Collection<NutritionalElement> rawMaterials(){

    
    return res;
}

You will need to understand what the intention is and you will need to create a Collection of NutritionalElement objects and return it.

0
Azizbek Sattorov On

Thank you guys. Here is how I solved the problem:

  1. I created classes for all Elements such as carbs, fat, etc. All implement NutritionalElement;
  2. implemented all necessary methods;
  3. Created 3 attributes in the Food instead of existing ones:
private ArrayList<NutritionalElement> elements;
private String name;
private HashMap<String, ArrayList<NutritionalElement>> allElements;
  1. Now the defining method looks like this:
public void defineRawMaterial(String name,
                                      double calories,
                                      double proteins,
                                      double carbs,
                                      double fat){
        this.name = name;
        elements.add(new Carbs(carbs));
        elements.add(new Fat(fat));
        elements.add(new Protein(proteins));
        elements.add(new Calories(calories));
        allElements.put(this.name, this.elements);
    }
  1. At the method I just wrote this and it all worked:
public Collection<NutritionalElement> rawMaterials(){
        return elements;
    }

The solution was inspired by Chaosfire, thank you man.

4
ODDminus1 On

I believe the requested answer is just asking for you to map the HashMap (weirdly named) rawMaterialsList to Collection of NutritionalElements. There are several ways to achieve this. You could use the Java-stream API on the map through rawMaterialsLists.entrySet().stream(), and map the entries of the map. Or you could loop over the entries with a for-loop.

It might also help to realize that you don't need to make specific implementations to each NutritionalElement. You can make an implementation in-line by writing

NutritionalElement myElement = new NutritionalElement() {
    public String getName() {
        // your implementation
    }
    // following methods for getCalories, getProteins etc.
}