枚举的各个值是否可以实现接口

时间:2015-12-03 19:42:23

标签: java enums

enum可以实现接口。某些值是否可以实现接口?我正在考虑的用例是标记接口,如下所示:

interface Foo {}
interface Bar {}

enum Widgets {
  FOO implements Foo,
  BAR_1 implements Bar,
  BAR_2 implements Bar
}

这不能在Java 1.8下编译。我知道在内部,为FOO和BAR_1创建了单独的类,所以看起来这是可能的,但我很容易看到标准不支持它。

类似的东西应该有效

interface Widgets;
enum Foo implements Widgets { FOO };
enum Bar implements Widgets { BAR_1, BAR_2 };

这样做的缺点是我不能只做Widgets.values()并获取所有小部件。

2 个答案:

答案 0 :(得分:4)

Java Language Specification

  

枚举常量的可选类主体隐式定义了一个   匿名类声明(第15.9.5节),立即扩展   封闭枚举类型。阶级机构由通常的规则管理   匿名课程;特别是它不能包含任何构造函数。   可以在外部调用在这些类主体中声明的实例方法   只有当它们覆盖可访问的方法时才包含枚举类型   封闭的枚举类型(§8.4.8)。

匿名类只能扩展(或实现)新实例创建表达式中指定的类型,在这种情况下为enum类型。因此,您无法另外实现接口。

以下

enum Foo {
    CONSTANT
}

被编译为类似于

的东西
class Foo extends Enum<Foo> {
    private Foo() {/* calling Enum superconstructor */}
    public static final Foo CONSTANT = new Foo();
}

如果你想让常量有一个体(覆盖或声明一些方法)

enum Foo {
    CONSTANT {
        public String toString() {
            return name().toUpperCase();
        }
    }
}

变得类似

class Foo extends Enum<Foo> {
    private Foo() {/* calling Enum superconstructor */}
    public static final Foo CONSTANT = new Foo() { // no way to express an additional interface
        public String toString() {
            return name().toUpperCase();
        }
    };
}

答案 1 :(得分:2)

枚举值不是类而是实例,因此它们无法实现接口。

但是,如果你想要的只是一种“标记”你的价值观的方法,你可以使用一个字段:

enum Widgets {

  FOO(true, false),
  BAR_1(false, true),
  BAR_2(false, true),
  BOTH(true, true);

  private final boolean isFoo;
  private final boolean isBar;

  Widgets(boolean isFoo, boolean isBar) {
    this.isFoo = isFoo;
    this.isBar = isBar;
  }

  public boolean foo() {
    return isFoo;
  }

  public boolean bar() {
    return isBar;
  }
}

在该示例中,您将能够使用Widgets.values()枚举您的值,并了解每个值是否标记为“foo”,“bar”或两者。

“标记”您的值的另一种方法可以是:

enum Tag {
  FOO,
  BAR;
}

enum Widgets {

  FOO(Tag.FOO),
  BAR_1(Tag.BAR),
  BAR_2(Tag.BAR),
  BOTH(Tag.FOO, Tag.BAR);

  private Tag[] tags;

  Widgets(Tag... tags) {
    this.tags = tags;
  }

  public Tag[] getTags() {
    return tags;
  }
}