在 Java 中,我想在抽象方法中实现具体行为,但遇到困难。
我的问题是,如果不使用转换或instanceofs,我无法获取执行操作的特定数据。我正在寻求帮助来更好地设计我的示例(最终是吸血鬼游戏)并学习一种新的实现方法。
示例: 人类与吸血鬼。人们吃提供糖/碳水化合物/蛋白质的普通食物(蛋糕等)。吸血鬼吃能提供血液的血食。食物的种类有很多种,这只是其中的两个例子。两者都是人。
Person 有一个 eat 方法,其类型为 Food。它检查该类型是否被允许(即:吸血鬼不能吃NormalFood,所以什么也不会发生)。 我的问题是检查后,我们如何在不使用强制类型转换或实例化的情况下将食物变成血液食物或普通食物。我能看到这一点的唯一方法是使用某种 getX(key) 方法,即: getInt("Sugar")、getFloat("Blood") 等。
我还能做什么?
这是我的代码示例:
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
{
}
您可以看到不同的食物具有不同的值,并且行为也会有所不同。例如,会有一个 ElderVampirePerson 每点会获得更多的血,所以他们的 eat 方法应该处理这种情况。
主要方法如下:
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);
最佳答案
如果您只有一种食物,这里是一个可以使用泛型的解决方案。
abstract class Person<F extends Food> {
abstract void eat(F food);
}
class NormalPerson extends Person<NormalFood> {
@Override
void eat(NormalFood food) { }
}
class Vampire extends Person<BloodFood> {
@Override
void eat(BloodFood food) { }
}
如果您需要处理多种食物,请考虑使用接口(interface)。
interface Eater<F extends Food> {
void eat(F food);
}
class NormalPerson implements Eater<NormalFood>, Eater<BloodFood> {
@Override
void eat(NormalFood f) {}
@Override
void eat(BloodFood f) {}
}
class Vampire implements Eater<BloodFood> {
@Override
void eat(BloodFood f) {}
}
关于java - 在抽象方法中比instanceof/cast更好的选择?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57242538/