0

Consider the following:

public class MainStarter {

    public static void main(String[] args) {

        Bread bread = new Bread();
        String breadType = "rye bread";
        String[] consumeBreadWith = {"butter","meat","peanut butter"};
        bread.setBreadType(breadType);
        bread.setConsumeWith(consumeBreadWith);

        consumeFood(bread);

        Meat meat = new Meat();
        String meatType = "roast beef";
        String[] consumeMeatWith = {"pepper","potatoes","green beans"};
        meat.setMeatType(meatType);
        meat.setConsumeWith(consumeMeatWith);

        consumeFood(meat);
    }
    // This is where I'm trying to figure out if I can reuse this method without having to overload it.
    public static void consumeFood(Object object) {

        Consume consume = new Consume();
        String result = consume.consumeWith(object);
        System.out.println(result);
    }
}
public class Consume {

    public String consumeWith(Bread bread) {
        return bread.enjoyWith();
    }

    public String consumeWith(Meat meat) {
        return meat.enjoyWith();
    }
}
public class Bread {

    private String breadType;
    private String[] sideDishes;

    public void setBreadType(String breadType) {
        this.breadType = breadType;
    }

    public String getBreadType() {
        return breadType;
    }

    public void setConsumeWith(String[] sideDishes) {
        this.sideDishes = sideDishes;
    }

    public String[] getConsumeWith() {
        return sideDishes;
    }

    public String enjoyWith() {
        String filter1 = Arrays.toString(getConsumeWith()).replace("[", "");
        String filter2 = filter1.replace("]", "");
        String[] stringArray = filter2.split(",");
        int length = stringArray.length;
        int num = 1;
        String sides = "";
        for (String element : stringArray) {
            if ( length == num ) {
                sides = sides + " or "+ element;
            } else {
                sides = sides + element + ",";
            }
            num++;
        }
        return "Enjoy "+getBreadType()+" with "+ sides +".";
    }
}
public class Meat {

    private String meatType;
    private String[] sideDishes;

    public void setMeatType(String meatType) {
        this.meatType = meatType;
    }

    public String getMeatType() {
        return meatType;
    }

    public void setConsumeWith(String[] sideDishes) {
        this.sideDishes = sideDishes;
    }

    public String[] getConsumeWith() {
        return sideDishes;
    }

    public String enjoyWith() {
        String filter1 = Arrays.toString(getConsumeWith()).replace("[", "");
        String filter2 = filter1.replace("]", "");
        String[] stringArray = filter2.split(",");
        int length = stringArray.length;
        int num = 1;
        String sides = "";
        for (String element : stringArray) {
            if ( length == num ) {
                sides = sides + " or "+ element;
            } else {
                sides = sides + element + ",";
            }
            num++;
        }
        return "Enjoy "+getMeatType()+" with "+ sides +".";
    }
}

I am hoping to reuse the "consumeFood" method of the main class and not have to overload it or find out what the Java best practice is. I eventually would like to add more model objects to the menu as well and this would cut down my code considerably if it could work. Thank you in advance for any respectful help you could offer. (I'm working in Java 17)

Chaosfire
  • 4,818
  • 4
  • 8
  • 23
  • 1
    You could introduce an abstract superclass like `Food` and then have both your classes extend it, `Meat extends Food` / `Bread extends Food` and then have your method accept any object of type `Food`. Or alternatively create some interface like `Consumable` that both classes implement and use that in the same way. – OH GOD SPIDERS Jul 07 '23 at 15:43
  • One thing you should know is that overloads are resolved at compile time, based on the type known to the compiler. So a call like `consume.consumeWith(object);` cannot take advantage of the run time type. – David Conrad Jul 07 '23 at 20:38

1 Answers1

3

Define common interface (or abstract class), and have your classes implement it. Let's say:

public interface Enjoyable {

  String enjoyWith();
}
public class Bread implements Enjoyable {

  @Override
  public String enjoyWith() {
    //do stuff
  }
}
public class Meat implements Enjoyable {

  @Override
  public String enjoyWith() {
    //do stuff
  }
}

Change method to work with the abstraction(Enjoyable):

public class Consume {

    public String consumeWith(Enjoyable enjoyable) {
        return enjoyable.enjoyWith();
    }
}

consumeWith() now works with any class implementing Enjoyable.

I would suggest to read this question - What does it mean to "program to an interface"?, it has some great answers on the topic.

Chaosfire
  • 4,818
  • 4
  • 8
  • 23