Java:包含内部枚举的接口;在实现类中扩展功能

Java:包含内部枚举的接口;在实现类中扩展功能,java,interface,enums,Java,Interface,Enums,我有一个如下所示的界面: package example; import java.awt.Point; public interface Thing { public enum MovingState { MOVING_LEFT, MOVING_UP, MOVING_RIGHT, MOVING_DOWN } public void setNewPosition(MovingState state);

我有一个如下所示的界面:

package example;
import java.awt.Point;

public interface Thing {
    public enum MovingState {
        MOVING_LEFT,
        MOVING_UP,
        MOVING_RIGHT,
        MOVING_DOWN
    }

    public void setNewPosition(MovingState state);
    public Point getPosition();
}
和一个实现类:

package example;
import java.awt.Point;

public class ThingImpl implements Thing {
    public enum MovingState {
        MOVING_LEFT (-1, 0),
        MOVING_UP (0, -1),
        MOVING_RIGHT (1, 0),
        MOVING_DOWN (0, 1);

        private int x_move;
        private int y_move;

        MovingState(int x, int y) {
            x_move = x;
            y_move = y;
        }

        public int xMove() {
            return x_move;
        }

        public int yMove() {
            return y_move;
        }
    }


    private Point position;

    public void setNewPosition(MovingState state) {
        position.translate(state.xMove(), state.yMove());
    }

    public Point getPosition() {
        return position;
    }
}
想法是让
ThingImpl
中的
MovingState
Thing
接口扩展
MovingState
(从而将
MovingState
的实际实现与接口分离)

但这不起作用-ThingImpl中的
MovingState
枚举将接口中的定义隐藏起来,而不是对其进行扩展,然后编译器会抱怨ThingImpl不是抽象的,并且不会覆盖Thing中的抽象方法setNewPosition(Thing.MovingState)


有没有一种实际的方法来实现我想要实现的目标?或者Java根本就没有这种功能?

您尝试的是一种反模式。不应在接口中定义常量


我会把常量移出你的接口,或者干脆把它们变成方法,让你的实现通过实现这些方法来定义它们…

你不能扩展
枚举,因为它是
最终的


您可能想阅读有效的Java第二版,第34项:使用接口模拟可扩展枚举。本质上,这归结为
枚举
本身,它实现了一些东西

多基因润滑油已经给了你答案。我想补充一点,因为这是我遇到的一个问题

假设您有一个包含许多实现的接口。接口中的一个方法将
enum
作为参数。理想情况下,您希望每个实现具有特定的枚举值集。但是,由于无法扩展枚举,因此无法创建“基本”枚举并从中进行扩展。天真的方法是使用一个“god”枚举来维护枚举值的完整集合。但是有更好的办法。您可以使用所谓的标记接口。《有效Java第二版》也谈到了这一点。标记接口将不包含任何方法声明,而只是将类标记为特定类型

因此,您可以定义一个标记接口,并让所有枚举实现该接口。这与使
enum
可扩展有关,因为如果定义了
enum
s可扩展的接口,则会自动将
enum
s标记为特定类型

通过这种方式,您可以保留所有特定枚举值及其特定实现(关注点分离)

对于您的情况,您可以这样做:

public interface MovingInterface {    
   int xMove();
   int yMove();
}
然后:

public enum MovingState implements MovingInterface {
    MOVING_LEFT (-1, 0),
    MOVING_UP (0, -1),
    MOVING_RIGHT (1, 0),
    MOVING_DOWN (0, 1);

    private int x_move;
    private int y_move;

    MovingState(int x, int y) {
        x_move = x;
        y_move = y;
    }

    public int xMove() {
        return x_move;
    }

    public int yMove() {
        return y_move;
    }
}

您真正想要做的是从“ThingImpl”类中删除enum声明,并将其全部(包括其构造函数和getter)移动到Thing接口中

将字段设置为枚举中的最终字段,以记住它们不应被触摸

以这种方式,任何希望使用Thing接口的东西都必须使用在接口上定义的枚举-您的问题是您实际上定义了它两次,但它应该在接口上(如果它只用于此接口,这很好),或者作为公共级别的enum Java文件(使用public enum而不是public类)。如果接口以外的其他对象可以合理地使用它,则可以将其设置为public enum-Map。在我看来,Entry是一个糟糕的嵌套接口,因为其他类使用了映射外部的键/值对,因此它应该是自己的接口,但我们必须接受它:(

想法是让ThingImpl中的MovingState从Thing接口扩展MovingState(从而将MovingState的实际实现与接口分离)

我不认为这真的是你的想法-我认为你在Thing的接口上指定的行为很好,你真的不想接触MovingState枚举,因为它很好。如果你认为某些东西需要MovingState的不同实现,但是,你可以让它实现一个名为MovingState的接口,这样你就可以d重命名枚举DefaultMovingState。这是您的选择


你的MovingState接口将只包含你现在在MovingState中公开的getter。两种方法。

-1-你错了,他没有做反模式。他所做的是愚蠢的,但它不是常量接口模式,因为他的接口定义了行为,而不只是用来保存常量值。在接口上定义常量是可以的,如果它们要与接口的行为结合使用。是的,我想这是正确的,我应该被否决。但是,这种方法是朝着错误的方向迈出的一步,我想我的建议是让他将左类型常量移动到方法中(可能放在抽象类中)仍然很好…他可以这样做,当然,但是如果他真的想添加额外的方向,那么他的界面将受到影响。那么将对角向上移动到左侧如何?这是另一种方法,但只是一个额外的枚举常量。你甚至可以创建更为深奥的枚举-横向移动,向上移动,然后向下移动。让每个枚举都变得简单作为一个单独的方法,NTD使接口膨胀。对于不能扩展,只有一半是正确的。每个枚举值都可以是一个匿名类,扩展您的枚举类。我没有访问这本书的权限,但从示例代码中可以看出,这一项没有涵盖我试图实现的内容。第34项似乎涵盖了扩展枚举以添加新常量,但我的目标只是添加成员函数。我的基类(Thing)中的枚举包含所有必需的常量。该功能正是我希望在实现类(ThingImpl)中隐藏的@Matthew:我认为
枚举
不适合定义抽象类型;
接口
更合适。也许你可以有一个可正交移动的
接口<