In Java, I want to implement concrete behavior in an abstract method but am having difficulty.
My issue is I cannot get the specific data to perform operations without using casting or instanceofs. I am looking for help to better design my example (eventually a vampire-game) and to learn a new way of doing it.
Example: People and Vampires. People eat NormalFood (cake, etc) that give sugar/carbs/proteins. Vampires eat BloodFood that give blood. There are going to be many types of food and these are just 2 examples. Both are Persons.
The Person has an eat method which takes type Food. It checks to see if the type is allowed (ie: Vampires can't eat NormalFood so nothing happens). My issue is after the check, how do we turn Food into BloodFood or NormalFood without using casts or instanceofs. The only way I can see this is by using some sort of getX(key) methods, ie: getInt("Sugar"), getFloat("Blood"), etc.
What else can I do?
Here are my code examples:
public abstract class Person
{
ArrayList<Class<? extends Food>> allowedFoods = new ArrayList();
public void eat(Food food)
{
System.out.println("------------------");
System.out.println("Person: " + this);
System.out.println(" Food: " + food);
boolean has = allowedFoods.contains(food.getClass());
System.out.println(" allowed: " + has);
if(has == false)
return;
eatHelper(food);
System.out.println("------------------");
}
abstract protected void eatHelper ( Food food );
}
public class HumanPerson extends Person
{
int fat;
int sugar;
int protein;
public HumanPerson()
{
allowedFoods.add(NormalFood.class);
}
@Override
protected void eatHelper ( Food food )
{
//How to get 'fat'/etc from the food without casting or using instanceof/etc.
//Can eventually accept other types of food instead of NormalFood, ie: PoisonedFood
}
}
public class VampirePerson extends Person
{
private int blood;
public VampirePerson()
{
allowedFoods.add(BloodFood.class);
}
@Override
protected void eatHelper ( Food food )
{
//How to get 'blood' from the food without casting or using instanceof/etc.
//Can eventually accept other types of food instead of BloodFood
}
}
public class NormalFood extends Food
{
int sugar = 100;
}
public class BloodFood extends Food
{
int blood = 50;
}
public class Food
{
}
You can see how the different foods have varying values and the behavior would vary. For example, there would be an ElderVampirePerson who would gain more blood per point, so their eat method should handle that situation.
Here is the main method:
Person person = new HumanPerson();
Person vampire = new VampirePerson();
Food foodOne = new NormalFood();
Food foodTwo = new BloodFood();
System.out.println("\nHuman is eating:");
person.eat(foodOne);
person.eat(foodTwo);
System.out.println("\nVampire is eating:");
vampire.eat(foodOne);
vampire.eat(foodTwo);