这可能是一个非常愚蠢的问题,但我想我会试着问!基本上问题是这样的:我可以在我的 setter 中使用 switch 语句吗?
这就是我正在做的事情:我创建了一个具有 healthPoints、描述、损坏和类型属性的 Monster 类,其中类型是一个枚举。在我的驱动程序中,我编写了几行代码,这些代码将从枚举值中随机生成一个怪物类型,并使用该类型创建一个新的怪物。
问题是当我显示怪物统计数据时,它显示 healthPoints 和伤害为 0,描述为空。当我尝试使用默认 Monster 构造函数运行程序时,它崩溃并显示 NullPointerException 错误。
我认为错误出在我的 setter 或构造函数中。每个 setter 里面都有一个 switch case,它根据随机生成的怪物类型设置一定数量的 healthPoints、伤害和具体描述。我不确定在 setter 中使用 switch 语句是否可以,因为我以前从未真正需要这样做。
这是我的一些代码。首先,我的构造函数。
public Monster(int healthPoints, monsterType type, int damage, String description)
{
setHealthPoints(healthPoints);
setType(type);
setDamage(damage);
setDescription(description);
}
public Monster(monsterType type)
{
setType(type);
}
Run Code Online (Sandbox Code Playgroud)
以下是其中一位二传手。
public void setHealthPoints(int healthPoints)
{
switch(type)
{
case DROW:
healthPoints = 30;
break;
case LICH:
healthPoints = 40;
break;
case ORC:
healthPoints = 20;
break;
case OWLBEAR:
healthPoints = 20;
break;
case RUST_MONSTER:
healthPoints = 10;
break;
}
this.healthPoints = healthPoints;
}
Run Code Online (Sandbox Code Playgroud)
下面是驱动程序中创建怪物的行。
int number = new Random().nextInt(monsterType.values().length);
Monster monster = new Monster(monsterType.values ()[number]);
Run Code Online (Sandbox Code Playgroud)
我希望根据生成的怪物类型设置怪物的健康点数、伤害和描述。我不确定这是否可以使用设置器中的开关来完成,我觉得我的错误可能很明显,我只是没有看到它,因为我已经盯着它看了很长时间......或者,如果有不同或更简单的方法可以做到这一点,请告诉我!感谢您抽出时间阅读;我试图让我的问题/问题彻底。
是的,您可以switch在构造函数和方法中使用案例。问题是您setHealthPoints之前调用过,setType但第一种方法type在其switch语句中使用了:
setHealthPoints(healthPoints);
setType(type);
Run Code Online (Sandbox Code Playgroud)
因此,变量type是未初始化当您访问switch的setHealthPoints,因此目前null。
一个switch语句将抛出NullPointerException,如果它的参数是null。这样你就得到了NPE。
您可以通过首先执行来解决这个问题setType。
您应该创建一个更易读的结构,它也更易于维护,尤其易于扩展。
因此考虑创建一个Monster 接口或抽象类。之后创建明确的怪物作为子类。该类Monster将包含所有怪物之间相等的所有内容,尝试从特定怪物中抽象出来。怪物本身将只包含与其他怪物不同的东西。
例如,您可以使用某种形式:
public abstract class Monster {
private int mHealthPoints;
private int mDamage;
private String mDescription;
public Monster(int healthPoints, int damage, String description) {
this.mHealthPoints = healthPoints;
this.mDamage = damage;
this.mDescription = description;
}
public int getHealthPoints() {
return this.mHealthPoints;
}
public int getDamage() {
return this.mDamage;
}
public String getDescription() {
return this.mDescription;
}
}
Run Code Online (Sandbox Code Playgroud)
然后你有特定的怪物类,比如
public class Orc extends Monster {
private static int HEALTH = 20;
private static int DAMAGE = 10;
private static String DESCRIPTION = "Nasty orc.";
public Orc() {
super(Orc.HEALTH, Orc.DAMAGE, Orc.DESCRIPTION);
}
}
Run Code Online (Sandbox Code Playgroud)
您也不再需要该monsterType 枚举,因为您可以通过monster instanceof Orc. 然而,对于真正的模块化设计,您不应该在特定的类上工作。而是使用大量描述属性和能力的接口。
例如接口,如:
CanAttack
IsAttackable
HasHealth
CanWalk
CanFly
CanCollide
...
Run Code Online (Sandbox Code Playgroud)
您的游戏逻辑可能只建立在这些接口上。例如CanAttack可能看起来像:
public interface CanAttack {
void attack(IsAttackable target);
}
Run Code Online (Sandbox Code Playgroud)
巨大的优势是您可以轻松扩展您的游戏。例如通过创建具有任意能力组合的怪物:
public SuperFlyingPig extends Monster implements
CanAttack, HasHealth, CanWalk, CanFly {
...
}
Run Code Online (Sandbox Code Playgroud)
而且它无需任何额外的编码工作即可神奇地工作,因为您的逻辑不会关心特定的怪物。它只适用于接口。