Enums with Abstract Methods

From the “I didn’t know that was possible” department:

Apparently by defining an abstract method on an enum the actual values can provide their own implementations of that method. Discovered this recently while digging around in some open source project. Handy. :)

  • mike

    Anyway, this is cleaner :

    public enum Animal {

    CAT(“MEOW!”),
    DOG(“WOOF!”),
    HORSE(“NEIGH!”);

    private final String noise;

    private Animal (String noise) {
    this.noise= noise;
    }

    public String makeNoise() {
    return noise;
    }

  • http://www.digitalsanctum.com Shane Witbeck

    I prefer using a private constructor and a getter. Same functionality, more concise code.

    • http://blog.james-carr.org James Carr

      Yes… this was just an example of something I wasn’t aware of. Although the example is contrived, there’s still cases where it could be useful. ;)

  • Sóstenes Barros

    It’s good to implement the strategy pattern.

  • Rahul

    This is very useful in some situations. I recently implemented the following using this trick.

    Calculate{

    minus {
    @Override
    public int calc(int o1, int o2) {
    return o1 - o2;
    }
    },
    plus {
    @Override
    public int calc(int o1, int o2) {
    return o1 + o2;
    }
    },
    divide {
    @Override
    public int calc(int o1, int o2) {
    if (o2 == 0) throw new RuntimeException("Divide by zero");
    return o1 / o2;
    }

    },
    times {
    @Override
    public int calc(int o1, int o2) {
    return o1 * o2;
    }
    };

    public abstract int calc(int o1, int o2);

    }

  • Tomáš Záluský

    In cases where method just returns a constant I consider it as antipattern because it expresses simple things in a complex way. It should be used only if logic denotes some operation, however, this reasoning is even weaker with JDK8 lambdas where you can use (borrowed from Rahul’s example):

    import java.util.function.BiFunction;

    public class HelloWorld {
    public static void main(String[] args) {
    System.out.print(Calc.PLUS.calc(3,4));
    }

    static enum Calc {
    PLUS((Integer o1, Integer o2) -> o1 + o2),
    MINUS((Integer o1, Integer o2) -> o1 – o2);

    private final BiFunction op;

    Calc(BiFunction op) {
    this.op = op;
    }

    public int calc(int o1, int o2) {
    return op.apply(o1,o2);
    }
    }
    }

    • Tomáš Záluský

      (I don’t get why disq.us changed my Integer with capital I to lowercase i.)