Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java8 using enum values in interface's default methods

I'm exploring possibilities of static and default methods introduced in java 8.

I've an interface that has 2 default methods that do construct a command, that I run on server through ssh to do some simple tasks remotely. Moving mouse requires 2 arguments: x and y position of the mouse.

public interface Robot {

    default String moveMouse(int x, int y) {
        return constructCmd("java -jar move_mouse.jar " + x + " " + y);
    }

    default String clickLeft() {
        return  constructCmd("java -jar click_left.jar");
    }

    static String constructCmd(String cmd) {
        return "export DISPLAY=:1.0\n" +
                "cd Desktop\n" +
                cmd;
    }
} 

I've multiple enums with values preset, I could potently combine all enums into one and not use interface what so ever, however that enum would contain hundreds or thousands of values and I want to keep it somewhat organised, so I've split evertying in multiple enums.

I want all enums to share same methods so I figured I'll give default methods in an interface a shot.

public enum Field implements Robot {

    AGE_FIELD(778, 232),

    NAME_FIELD(662, 280);

    public int x;
    public int y;

    Field(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

So I can get String commands by:

Field.AGE_FIELD.clickLeft();
Field.AGE_FIELD.moveMouse(Field.AGE_FIELD.x, Field.AGE_FIELD.y);

However moveMouse looks really bad to me and I think it should be somehow possible to use enum's values by default.

Anyone has a a nice solution for such problem?

like image 959
user2821023 Avatar asked Feb 05 '23 20:02

user2821023


1 Answers

The problem is your architecture. On the one hand, you have a layer that actually executes the mouse-movement (represented by your Robot interface). Now, you need a layer that produces mouse-movement and sends it to a Robot to execute this mouse-movement. Let's call the interface defining this layer MouseTarget (fits your example nicely):

public interface MouseTarget {
    int getTargetX();
    int getTargetY();

    default void moveMouseHere(Robot robot) {
        robot.moveMouse(this.getTargetX(), this.getTargetY());
    }
}

This interface represents one mouse-movement to one target. As you see the moveMouseHere(Robot robot) method expects a Robot to send the movement to (which does the actual work). Now, all what is left is to adapt your Fields enum:

public enum Fields implements MouseTarget {

    AGE_FIELD(778, 232), NAME_FIELD(662, 280);

    public int targetX;
    public int targetY;

    Fields(int targetX, int targetY) {
        this.targetX = targetX;
        this.targetY = targetY;
    }

    @Override
    public int getTargetX() {
        return targetX;
    }

    @Override
    public int getTargetY() {
        return targetY;
    }
}
like image 98
Turing85 Avatar answered Feb 08 '23 15:02

Turing85