[英]Java: Interfaces containing inner enums; Extending functionality in implementation classes
我有一个如下界面:
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;
}
}
我们的想法是让MovingState
中的ThingImpl
从Thing
接口扩展MovingState
(从而将MovingState
的实际实现与接口分开)。
这不起作用 - MovingState
中的MovingState
枚举ThingImpl
影响接口中的定义而不是扩展它,然后编译器抱怨ThingImpl不是抽象的,并且不会覆盖Thing中的抽象方法setNewPosition(Thing.MovingState)。
有没有一种实际的方法来做我想要实现的目标? 或者Java根本没有这种能力?
你真正想要做的是从你的“ThingImpl”类中删除枚举声明,并将所有这些声明(包括它的构造函数和getter)移动到Thing界面中。
让你的字段在枚举中最后记住它们不应该被触及。
以这种方式,任何希望使用Thing接口的东西都必须使用你接口上定义的枚举 - 你的问题是你有效地定义了两次,但它应该在接口上(如果只使用它就没问题)对于此接口)或作为公共级枚举Java文件(使用公共枚举而不是公共类)。 如果你的界面之外的其他东西可以合理地期望使用它,你就会把它变成公共枚举 - 在我看来,Map.Entry是一个糟糕的嵌套接口,因为其他类用于地图外部的键/值对因此它应该是它自己的界面,但我们必须忍受它:(
我们的想法是让ThingImpl中的MovingState从Thing接口扩展MovingState(从而将MovingState的实际实现与接口分开)。
我不认为这是你的想法 - 我认为你在Thing接口上指定的行为很好,你真的不想触摸MovingState枚举,因为它很好。 但是,如果您认为某些内容需要不同的MovingState实现,则可以使其实现名为MovingState的接口,从而可以重命名枚举DefaultMovingState。 这是你的选择。
您的MovingState接口将立即拥有您在MovingState中公开的getter。 两种方法。
你不能扩展enum
因为它是final
。
您可能希望阅读Effective Java 2nd Edition,Item 34:使用接口模拟可扩展枚举 。 从本质上讲,这归结为implements Something
的enum
本身。
polygenelubricants给了你答案。 我想补充一些东西,因为这是我遇到的一个问题。
假设您有一个具有许多实现的接口。 接口中的一种方法将enum
作为参数。 理想情况下,您希望每个实现具有特定的枚举值集。 但是,由于您无法扩展枚举,因此无法创建“基础”枚举并从中扩展。 天真的方法是拥有一个“上帝”枚举,它维护着一整套枚举值。 但还有更好的方法。 您可以使用所谓的标记界面 。 有效的Java第二版。 也谈到这一点。 标记接口不包含任何方法声明,只是将类标记为某种类型。
因此,您可以定义标记接口,并让所有枚举实现该接口。 这关系到使enum
可扩展的,因为如果你定义自己的接口enum
小号扩展,你已经自动标记您的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;
}
}
你正在尝试的是反模式。 不应在接口中定义常量。
http://en.wikipedia.org/wiki/Constant_interface
我会将常量移出你的界面,或者只是让它们成为方法,让你的实现通过实现这些方法来定义它们......
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.