在 setter 中使用 switch 语句

Lin*_* M. 2 java setter

这可能是一个非常愚蠢的问题,但我想我会试着问!基本上问题是这样的:我可以在我的 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)

我希望根据生成的怪物类型设置怪物的健康点数、伤害和描述。我不确定这是否可以使用设置器中的开关来完成,我觉得我的错误可能很明显,我只是没有看到它,因为我已经盯着它看了很长时间......或者,如果有不同或更简单的方法可以做到这一点,请告诉我!感谢您抽出时间阅读;我试图让我的问题/问题彻底。

Zab*_*uza 5

解释

是的,您可以switch在构造函数和方法中使用案例。问题是您setHealthPoints之前调用过,setType但第一种方法type在其switch语句中使用了:

setHealthPoints(healthPoints);
setType(type);
Run Code Online (Sandbox Code Playgroud)

因此,变量type未初始化当您访问switchsetHealthPoints,因此目前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)

而且它无需任何额外的编码工作即可神奇地工作,因为您的逻辑不会关心特定的怪物。它只适用于接口