我刚刚发现Java允许枚举实现接口。它的一个好的用例是什么?


当前回答

这里一些人给出的可比示例是错误的,因为Enum已经实现了这一点。你甚至不能重写它。

一个更好的例子是有一个定义数据类型的接口。你可以使用枚举来实现简单类型,也可以使用普通类来实现复杂类型:

interface DataType {
  // methods here
}

enum SimpleDataType implements DataType {
  INTEGER, STRING;

  // implement methods
}

class IdentifierDataType implements DataType {
  // implement interface and maybe add more specific methods
}

其他回答

枚举不只是表示被动的集合(例如颜色)。它们可以表示具有功能的更复杂的对象,因此你可能想要在这些对象上添加更多的功能——例如,你可能有诸如Printable、Reportable等接口,以及支持这些接口的组件。

在jar文件中创建常量时,让用户扩展枚举值通常是有帮助的。我们为PropertyFile键使用了枚举,但是因为没有人能够添加任何新的键而陷入了僵局!下面的效果会好得多。

考虑到:

public interface Color {
  String fetchName();
}

and:

public class MarkTest {

  public static void main(String[] args) {
    MarkTest.showColor(Colors.BLUE);
    MarkTest.showColor(MyColors.BROWN);
  }

  private static void showColor(Color c) {
    System.out.println(c.fetchName());
  }
}

一个容器中可以有一个enum:

public enum Colors implements Color {
  BLUE, RED, GREEN;
  @Override
  public String fetchName() {
    return this.name();
  }
}

用户可以扩展它来添加自己的颜色:

public enum MyColors implements Color {
  BROWN, GREEN, YELLOW;
  @Override
  public String fetchName() {
    return this.name();
  }
}

下面是一个例子(在Effective Java 2nd Edition中有一个类似的/更好的例子):

public interface Operator {
    int apply (int a, int b);
}

public enum SimpleOperators implements Operator {
    PLUS { 
        int apply(int a, int b) { return a + b; }
    },
    MINUS { 
        int apply(int a, int b) { return a - b; }
    };
}

public enum ComplexOperators implements Operator {
    // can't think of an example right now :-/
}

现在要获得简单+复杂操作符的列表:

List<Operator> operators = new ArrayList<Operator>();

operators.addAll(Arrays.asList(SimpleOperators.values()));
operators.addAll(Arrays.asList(ComplexOperators.values()));

因此,在这里您使用一个接口来模拟可扩展枚举(如果不使用接口,这是不可能的)。

我在一个接口中使用了一个内部枚举来描述一个策略来保持实例控制(每个策略都是一个Singleton)。

public interface VectorizeStrategy {

    /**
     * Keep instance control from here.
     * 
     * Concrete classes constructors should be package private.
     */
    enum ConcreteStrategy implements VectorizeStrategy {
        DEFAULT (new VectorizeImpl());

        private final VectorizeStrategy INSTANCE;

        ConcreteStrategy(VectorizeStrategy concreteStrategy) {
            INSTANCE = concreteStrategy;
        }

        @Override
        public VectorImageGridIntersections processImage(MarvinImage img) {
            return INSTANCE.processImage(img);
        }
    }

    /**
     * Should perform edge Detection in order to have lines, that can be vectorized.
     * 
     * @param img An Image suitable for edge detection.
     * 
     * @return the VectorImageGridIntersections representing img's vectors 
     * intersections with the grids.
     */
    VectorImageGridIntersections processImage(MarvinImage img);
}

枚举实现该策略的事实便于允许枚举类充当其所包含的Instance的代理。其中也实现了接口。

它是一种strategyEnumProxy:P,客户端代码看起来像这样:

VectorizeStrategy.ConcreteStrategy.DEFAULT.processImage(img);

如果它没有实现接口,它将是:

VectorizeStrategy.ConcreteStrategy.DEFAULT.getInstance().processImage(img);

最常见的用法是将两个枚举的值合并到一个组中,并以类似的方式对待它们。例如,查看如何加入水果和蔬菜。