I have an interface like the following:
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();
}
and an implementation class:
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;
}
}
The idea is to have MovingState
in ThingImpl
extend MovingState
from the Thing
interface (thus separating the actual implementation of MovingState
from the interface).
This doesn't work though - the MovingState
enum in ThingImpl
shadows the definition in the interface instead of extending it, then the compiler complains that ThingImpl is not abstract and does not override abstract method setNewPosition(Thing.MovingState) in Thing.
Is there an actual way to do what I'm trying to achieve? Or does Java simply not have this capability?
We cannot extend enum classes in Java. It is because all enums in Java are inherited from java. lang. Enum .
Yes, Enum implements an interface in Java, it can be useful when we need to implement some business logic that is tightly coupled with a discriminatory property of a given object or class.
It's perfectly legal to have an enum declared inside an interface . In your situation the interface is just used as a namespace for the enum and nothing more. The interface is used normally wherever you use it.
Note: All enums implicitly extend java. lang.
What you really want to do is remove the enum declaration from your "ThingImpl" class and move all of it (including its constructor and getters) into the Thing interface.
Make your fields final in the enum to remember that they shouldn't be touched.
In this fashion, anything wishing to use the Thing interface must use the enumeration defined on your interface - your problem is that you're effectively defining it twice, but it should either be on the interface (which is fine if it will only be used for this interface) or as a public level enum Java file (using public enum instead of public class). You'd make it a public enum if something other than your interface could reasonably expect to use it - Map.Entry, in my opinion, is a bad nested interface because other classes have use for a key/value pair external to a map and thus it should be its own interface, but we have to live with it :(
The idea is to have MovingState in ThingImpl extend MovingState from the Thing interface (thus separating the actual implementation of MovingState from the interface).
I don't think this is really your idea - I think the behavior you've specified on the interface of Thing is fine, you really don't want to touch the MovingState enum as it's fine as it is. If you think something needs a different implementation of MovingState, however, you can make it implement an interface called MovingState and thus you could rename your enum DefaultMovingState. It's your choice.
Your MovingState interface would simply have the getters you're exposing in MovingState right now. Two methods.
You can't extend an enum
because it's final
.
You may want to read Effective Java 2nd Edition, Item 34: Emulate extensible enums with interfaces. Essentially this boils down to the enum
itself that implements Something
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With