Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Interfaces containing inner enums; Extending functionality in implementation classes

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?

like image 892
MatthewD Avatar asked Jul 13 '10 22:07

MatthewD


People also ask

Can enum extend a class in Java?

We cannot extend enum classes in Java. It is because all enums in Java are inherited from java. lang. Enum .

Can enums implement interface Java?

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.

Can enums be defined inside an interface?

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.

Which class does all the enums extend?

Note: All enums implicitly extend java. lang.


2 Answers

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.

like image 138
MetroidFan2002 Avatar answered Sep 23 '22 06:09

MetroidFan2002


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.

like image 29
polygenelubricants Avatar answered Sep 21 '22 06:09

polygenelubricants