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


当前回答

在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()));

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

上面提到的策略并没有充分强调使用枚举的策略模式的轻量级实现:

public enum Strategy {

  A {
    @Override
    void execute() {
      System.out.print("Executing strategy A");
    }
  },
  
  B {
    @Override
    void execute() {
      System.out.print("Executing strategy B");
    }
  };

  abstract void execute();
}

你可以把所有的策略放在一个地方,而不需要为每个策略单独编译单元。你得到了一个很好的动态调度:

Strategy.valueOf("A").execute();

使java读起来几乎像一种美味的松散类型语言!

枚举不只是表示被动的集合(例如颜色)。它们可以表示具有功能的更复杂的对象,因此你可能想要在这些对象上添加更多的功能——例如,你可能有诸如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();
  }
}

由于枚举可以实现接口,它们可以用于严格执行单例模式。试着让一个标准类成为单例允许…

获奖理由:可以使用反射技术将私有方法公开为公共方法 用于从你的单例中继承和用其他东西重写你的单例方法

作为单例的枚举有助于防止这些安全问题。这可能是让enum充当类并实现接口的原因之一。只是猜测。

更多讨论请参见https://stackoverflow.com/questions/427902/java-enum-singleton和java中的Singleton类。