Question

I have an interface and I want enum to implement it, but some methods are identical and it causes code duplication. I would use abstract class instead of interface, but java doesn't allow enums to extend anything. Is there a way around this? I include some code to help understand the problem.

public interface CommandI {
  boolean isCommand(String command);
  void execute(Drawer drawer, Creature creature);
  String getDescription();
}



public enum Command2 implements CommandI {
  FORWARD{
    private String description = "qwersadd";
    private String[] aliases = {"fd", "forward"};
    @Override
    public boolean isCommand(String command) {
        for (String s: aliases){
        if (s.equals(command)){
          return true;
        }
      }
      return false;
    }
    @Override
    public void execute(Drawer drawer, Creature creature) {
      throw new UnsupportedOperationException("Not supported yet.");
    }
    @Override
    public String getDescription() {
      return description;
    }
  },
  PENUP{
    private String description = "vcvzxcvz";
    private String[] aliases = {"pu", "penup"};
    @Override
    public boolean isCommand(String command) {
        for (String s: aliases){
        if (s.equals(command)){
          return true;
        }
      }
      return false;
    }
    @Override
    public void execute(Drawer drawer, Creature creature) {
      throw new UnsupportedOperationException("Not supported yet.");
    }
    @Override
    public String getDescription() {
      return description;
    }
  }

}

As you see, only the execute method would differ.

Was it helpful?

Solution

I'm not sure you really understood how enums are intended to be used. Here is the way you should have implement Command2:

public enum Command2 implements CommandI {

    FORWARD("qwersadd", new String[] { "fd", "forward" }),
    PENUP("vcvzxcvz", new String[] { "pu", "penup" });

    private final String description;
    private final String[] aliases;

    private Command2(String description, String[] aliases) {
        this.description = description;
        this.aliases = aliases;
    }

    @Override
    public boolean isCommand(String command) {
        for (String s : aliases) {
            if (s.equals(command)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void execute(Drawer drawer, Creature creature) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public String getDescription() {
        return description;
    }

}

The time you want to implement the execute body of FORWARD for example, simply (over-)override it as follow:

FORWARD("qwersadd", new String[] { "fd", "forward" }) {
    @Override
    public void execute(Drawer drawer, Creature creature) {
        // specific execute body for FORWARD
    }
}

OTHER TIPS

You can define abstract methods in the enum itself, and use the template method pattern:

public enum Command2 implements CommandI {
    FORWARD {
        private String description = "qwersadd";
        private String[] aliases = {"fd", "forward"};

        @Override
        protected String[] getAliases() {
            return aliases;
        }

        @Override
        public String getDescription() {
            return description;
        }
    },
    PENUP {
        private String description = "vcvzxcvz";
        private String[] aliases = {"pu", "penup"};

        @Override
        protected String[] getAliases() {
            return aliases;
        }

        @Override
        public String getDescription() {
            return description;
        }
    };

    protected abstract String[] getAliases();

    @Override
    public boolean isCommand(String command) {
        for (String s : getAliases()) {
            if (s.equals(command)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public void execute(Drawer drawer, Creature creature) {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}

But in this particular case, since all methods are implemented the same way, and all enums have the same state, the answer from @sp00m is a better way of solving your problem.

This reply is mostly academic, but it does answer the question. If it's not useful, I apologize.

If you REALLY wanted to solve this, you could do a bit of roundabout. You could create an abstract class extending enum and then put your implementations in there. THEN you could create another class that extends your AbstractEnum class and implements ICommand. This would probably be the most kosher way of doing things.

However, if you just want to churn this out you could add a Runnable and pass it in through the constructor..

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top