gpt4 book ai didi

java - 这里的最佳实践是什么,扩展 `enum` 真正有用(但在 java 中是不可能的)?

转载 作者:行者123 更新时间:2023-11-30 02:54:03 26 4
gpt4 key购买 nike

我正在制作一个游戏,并且我有一组类:Character extends MovingEntity extends Entity

第一个只有一个位置和一些其他字段。 MovingEntity 正如其名称所示,可以移动。我曾经用枚举enum State{IDLE, MOVING}来表示这一点。然而,当我实现Character时,我遇到了一个问题,因为它们也可以攻击!

所以,有一段时间我正在处理一个尴尬的事情

Class MovingEntity extends Entity{
public enum State{
IDLE, MOVING;
}
}
Class Character extends MovingEntity {
public enum CharacterState{
IDLE, MOVING, ATTACKING
}

当我添加更复杂的字符时,甚至会发生更多的“枚举覆盖”。所以我最终切换到 public static final int 常量...但我在这里读到这被认为是一种非常糟糕的做法(我不明白为什么,因为 Java 的 API 就是这样做的( KeyEvent.VK_stuff 是整数,JFrame 关闭时的默认操作也是...)。

这里的最佳实践是什么?

最佳答案

您可以有一个包含所有可能状态的枚举。然后,每个实体声明它们支持哪些状态:

enum State{
IDLE, MOVING, ATTACKING;
}

class Entity {
private State[] states;

protected Entity(State... states) {
this.states = states;
}

}

class Character extends Entity{
public Character() {
super(State.IDLE, State.MOVING, State.ATTACKING);
}
}

class MovingEntity extends Entity{
public MovingEntity() {
super(State.IDLE, State.MOVING);
}
}

如果您创建专门的角色,您甚至可以“继承”其 parent 的状态。

class FastMovingEntity extends MovingEntity{
public FastMovingEntity() {
super(State.MOVING_FAST);
}
}

class MovingEntity extends Entity{
public MovingEntity(State... states) {
super(...);
}
}

为什么是枚举?

我本人认为枚举优于常量,因为它们是强类型的并且更易于阅读。例如:

doStuff(int state);
doStuff(State state);

第二种方法不言而喻,就参数而言,这个名字可能更好:)。此外,边界更容易验证,无论您拥有有效状态还是空状态。 (而不是拥有一系列有效的整数,必须通过javadoc记录它,以便用户知道如何使用你的方法)

最后,枚举允许您添加行为(方法),而常量不允许您这样做。

例如:

enum State {
IDLE, MOVING, ATTACKING(false), MOVING_FAST;

private boolean someFlag;

State(boolean someFlag) {
this.someFlag = someFlag;
}

State() {
this(true);
}

public boolean isSomeFlag() {
return someFlag;
}
}

此外,KeyEvent.VK_stuff 使用整数,但主要原因很简单,因为它在枚举存在之前就已经存在了。

关于评论中您的其他问题

every time I use a State variable inside each class, to actually validate that it is a valid state, I would have to check if it's equal to some value in the State[] states array?

这是我从你的陈述中了解到的。假设发出了更改角色状态的请求。您首先需要检查该角色是否支持状态更改。所以你最终会一直在数组上循环。这是你的问题吗?

如果是这样,那么您可以使用 Set 来代替 Entity 中的数组,并使用一个返回状态是否受支持的方法:

class Entity {
private EnumSet<State> supportedStates;
private State currentState;

protected Entity(State... state) {
states = EnumSet.copyOf(Arrays.asList(state));
}

//Assumes you are using these values elsewhere, otherwise - private
public boolean isStateSupported(State state){
return supportedStates.contains(state);
}

public void setCurrentState(State currentState){
if(!isStateSupported(currentState){
throw new IllegalStateException();
}
this.currentState = currentState;
}
public State getCurrentState(){
return currentState;
}
}

编辑(6 月 15 日):我添加了 setCurrentState 方法。使用此方法,您可以设置当前状态,这首先验证该值是否受支持 (isStateSupported)。如果支持的状态列表仅在内部用于验证,则 isStateSupported 可能是私有(private)的,但我的猜测是您应该从其他地方调用此方法以用于其他目的。也许,用户不应该有设置无效状态的选项,因此您的用户界面将在显示选项之前首先检查什么是有效状态。我希望我说得清楚......

关于java - 这里的最佳实践是什么,扩展 `enum` 真正有用(但在 java 中是不可能的)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37781337/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com