tags:

views:

110

answers:

3

I am doing astrophysical research. I wrote a package containing the classes Star, Band, and Datfile. I also have the enumerated type of BandName. Each star contains several Bands, each Band contains several Datfiles.

I have observational data for several galaxies. For each of these, I make a StarDatabase class (a HashMap of Stars) and a Main class.

The problem I'm having is with the enumerated type of BandName. So far, all of the data I have used has been in the I and V bands. Now I have data in J, H, and K bands. If I simply add J, H, and K to BandName, all of my loops that iterate over all of the items in BandName and do something are now broken.

Any ideas?

Edit: To sum up my problem, I want every package to have its own BandName enum that it can iterate through. But this doesn't work, because the methods in the Star package are expecting objects of type Star.BandName and I am providing objects of type IndividualPackage.BandName.

+8  A: 

You can't inherit an enum from another enum, although you can have your enum implement an interface. The technical problem (that all enums implicitly extend java.lang.Enum, thus they can't extend another class, only implement additional interfaces) is no accident:

For the most part, extensibility of enums turns out to be a bad idea. It is confusing that elements of an extension type are instances of the base type and not vice versa. There is no good way to enumerate over all of the elements of a base type and its extension. Finally, extensibility would complicate many aspects of the design and implementation.

From Effective Java 2nd Edition, Item 34.

However, I don't fully understand your problem: haven't you used values() for iterating through your enum? Then you shouldn't worry about extending your enum with new values.

Please specify more clearly what "broken" is supposed to mean.

Update: so you need to have distinct sets of bands for different types of stars - this can be implemented using distinct enums extending a common interface, e.g.:

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 */ }
  ...
}

And you can use these by making your Star class generic:

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

This works nicely if the bands are organized into distinct groups. If there are stars with mixed band groups, however, you might prefer an alternative approach:

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}));
...

This allows you to set up stars with an arbitrary mix of bands. However, this way you can't use EnumSet or EnumMap on the bands.

Péter Török
For example, every Star object iterates through BandName.values() and adds a new Band with the named value. Then that Band looks in the directory /value to get the datfiles. Then the GUI makes a new BandRadioButton out of each Band in BandName.values()... so on and so forth.
Earl Bellinger
@Earl, I still don't get where the problem lies: is the datfile for the new bands missing, or does the GUI get messed up, or ...?
Péter Török
The GUI does indeed get messed up. The stars that concern themselves with the V and I bands should not interact with the J, H, or K at all.I want it to iterate through the values (instead of explicitly naming them) in case a new band _does_ need to be added.
Earl Bellinger
@Earl, I see. So you have stars with only the V and I bands. How about the rest - are they concerned only with the J, H and K bands, or with all bands?
Péter Török
Only J, H, and K.
Earl Bellinger
@Earl, see my update.
Péter Török
A: 

All enums implicitly extend java.lang.Enum. Since Java does not support multiple inheritance an enum cannot extend anything else. - http://download.oracle.com/javase/tutorial/java/javaOO/enum.html

reverendgreen
I know this. Hence the question.
Earl Bellinger
@Earl, he had no way to know you knew this. It is difficult to impossible for us to give you good answers if you don't give us enough information on the problem.
Péter Török
I apologize. That was not intended to sound rude.
Earl Bellinger
A: 

This is what I'd do (pseudo-code):

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)
}

This way you can add bands by just creating more Band objects. Each start has the list of bands it uses so it can iterate over all them.

Winston Ewert