Java中的枚举继承?

Posted

技术标签:

【中文标题】Java中的枚举继承?【英文标题】:Enumeration inheritance in Java? 【发布时间】:2010-08-06 21:31:56 【问题描述】:

我正在做天体物理学研究。我编写了一个包含 Star、Band 和 Datfile 类的包。我也有 BandName 的枚举类型。每颗星包含几个波段,每个波段包含几个数据文件。

我有几个星系的观测数据。对于其中的每一个,我创建了一个 StarDatabase 类(一个星的 HashMap)和一个 Main 类。

我遇到的问题是 BandName 的枚举类型。到目前为止,我使用的所有数据都在 I 和 V 波段。现在我有 J、H 和 K 波段的数据。如果我只是将 J、H 和 K 添加到 BandName,那么我所有遍历 BandName 中所有项目并执行某些操作的循环现在都会中断。

有什么想法吗?

编辑:总结一下我的问题,我希望每个包都有自己的 BandName 枚举,它可以迭代。但这不起作用,因为 Star 包中的方法需要 Star.BandName 类型的对象,而我提供的是 IndividualPackage.BandName 类型的对象。

【问题讨论】:

你为什么要遍历 BandNames? 如果确实需要添加新的乐队,我使用乐队名的任何地方都不需要更新。 包对应什么?也就是说,您为什么首先要对这些类进行子类化? 我有几个包,每个星系一个,都需要用到Star、Band和Datfile。它们都有不同的 StarDatabase(因为它们所有的数据都由其他人以不同的方式组织)和 Main 类,其中两个有 GUI。 add values to enum的可能重复 【参考方案1】:

你不能从另一个枚举继承一个枚举,尽管你可以让你的枚举实现一个接口。技术问题(所有枚举都隐式扩展java.lang.Enum,因此它们不能扩展另一个类,只能实现附加接口)并非偶然:

在大多数情况下,枚举的可扩展性结果是 是个坏主意。扩展类型的元素是 基本类型,反之亦然。没有很好的方法来枚举所有 基本类型的元素及其扩展。最后,可扩展性会变得复杂 设计和实现的许多方面。

来自Effective Java 2nd Edition,第 34 条。

但是,我不完全理解您的问题:您没有使用values() 来遍历您的枚举吗?那么你不应该担心用新值扩展你的枚举。

请更清楚地说明“破碎”的含义。

更新:因此您需要为不同类型的星星设置不同的波段 - 这可以使用扩展通用接口的不同枚举来实现,例如:

interface Band 
  String getName();
  void doStuff();
  ...


enum BandsVI implements Band 
  V, I;
  public String getName()  return toString(); 
  public void doStuff()  /* do stuff as appropriate for these bands */ 
  ...


enum BandsJHK implements Band 
  J, H, K;
  public String getName()  return toString(); 
  public void doStuff()  /* do stuff as appropriate for these bands */ 
  ...

您可以通过使您的 Star 类通用化来使用这些:

class Star<T extends Enum<T> & Band> 
  private Class<T> bandType;
  public Star(Class<T> bandType)  this.bandType = bandType; 
  public void printBandNames() 
    for (Band b : bandType.getEnumConstants())
      System.out.println(b.getName());
  
  public void doStuffOnAllBands() 
    for (Band b : bandType.getEnumConstants())
      b.doStuff();
  

...
Star<BandsVI> star1 = new Star<BandsVI>(BandsVI.class);
Star<BandsJHK> star2 = new Star<BandsJHK>(BandsJHK.class);
star1.printBandNames(); // prints V I
star2.printBandNames(); // prints J H K

如果将乐队组织成不同的组,这会很好地工作。但是,如果有混合乐队的明星,您可能更喜欢另一种方法:

class Star 
  private List<? extends Band> bandTypes;
  public Star(List<? extends Band> bandTypes)  this.bandTypes = bandTypes; 
  public void printBandNames() 
    for (Band b : bandTypes)
      System.out.println(b.getName());
  
  ...


...
Star star1 = new Star(Arrays.asList(BandsVI.values()));
Star star3 = new Star(Arrays.asList(new Band[]BandsVI.V, BandsVI.I, BandsJHK.K));
...

这使您可以使用任意组合的波段来设置星星。但是,这样您就不能在频段上使用EnumSetEnumMap

【讨论】:

例如,每个 Star 对象都会遍历 BandName.values() 并添加一个具有命名值的新 Band。然后那个 Band 在目录 /value 中查找以获取 datfiles。然后 GUI 从 BandName.values() 中的每个 Band 中创建一个新的 BandRadioButton... 以此类推。 @Earl,我仍然不明白问题出在哪里:新频段的 datfile 是否丢失,或者 GUI 是否混乱,或者...? GUI 确实搞砸了。与 V 和 I 波段有关的恒星根本不应该与 J、H 或 K 相互作用。我希望它遍历这些值(而不是显式命名它们),以防需要添加新的乐队 确实 @Earl,我明白了。所以你有只有 V 和 I 波段的明星。其余的呢?他们只关注 J、H 和 K 波段,还是关注所有波段?【参考方案2】:

所有枚举都隐式扩展 java.lang.Enum。由于 Java 不支持多重继承,因此枚举不能扩展其他任何东西。 - http://download.oracle.com/javase/tutorial/java/javaOO/enum.html

【讨论】:

我知道这一点。因此问题。 @Earl,他无法知道你知道这一点。如果您没有就该问题向我们提供足够的信息,我们很难或不可能给您提供好的答案。 我很抱歉。这听起来并不粗鲁。【参考方案3】:

这就是我要做的(伪代码):

class Band

     String name;
;
static Band J("J");
static Band K("K");

static ArrayList<Band> JK;
static ArrayList<Band> IHL;

class Star

    Star(ArrayList<Band> bands)

这样您就可以通过创建更多的 Band 对象来添加 Band。每个起点都有它使用的波段列表,因此它可以遍历所有波段。

【讨论】:

以上是关于Java中的枚举继承?的主要内容,如果未能解决你的问题,请参考以下文章

java中的枚举类

java中的枚举类型

java的枚举类enum,定义静态变量还可以有抽象方法,但枚举类不能被继承

java中枚举的常见用法

[JAVA]枚举类型的应用

java怎么声明枚举类型