tags:

views:

309

answers:

3

How can I have an abstract enum, or some kind of base enum?

In my common code I'd like a notion of an enum placeholder, MyItems, without tying myself to a concrete enum. Then in each of my projects I would have a concrete implementation.

E.g. Common Code

public interface MyItems {
    // Marker interface
}

Project A

public enum Items implements MyItems {
     RED_CAR, BLUE_CAR, GREEN_CAR;
}

Project B

public enum Items implements MyItems {
    BROWN_TREE, GREEN_TREE;
}

This seems to work, but in my common code I can't write a loop over my interface enum, since it's not an enum. In my common code I'd like to write

for (MyItems item : MyItems.values())
    doSomething(item);

but I can't because my interface is just a marker interface, and it doesn't have a .values().

Any suggestions greatly appreciated. I don't know if I'm trying in completely the wrong way.

+7  A: 

It doesn't really make sense to do this - because the values() method is static. To call it, you need to know the type you want to call it on.

The closest you could come would be to have:

public interface MyItemsFactory<T extends MyItems>
{
    Iterable<T> values();
}

and then implement that in some generic way, e.g.

public class EnumFactory<T extends Enum<T> & MyItems>
    implements MyItemsFactory<T>
{
    private final Class<T> clazz;

    public EnumFactory(Class<T> clazz)
    {
        this.clazz = clazz;
    }

    public Iterable<T> values()
    {
        return EnumSet.allOf(clazz);
    }
}

But the basic rule is that polymorphism and static methods don't mix. In your call:

for(MyItems item : MyItems.values())
    doSomething(item);

which implementation of MyItems would you expect it to iterate over? You could have loads of types implementing MyItems.

Jon Skeet
Thanks for your answer which I will study and try to understand fully. To answer your question, I don't think I was very clear. My ideal is to be able to 'inject' an enum which I'd like to use, which will change in each project that uses the common code. I'd then like the common code to be able to iterate over the enum and do stuff.
Pengin
If it needs to be able to iterate over it and you want to do so polymorphically, what you need to inject is the factory shown in my answer. That will allow you to iterate over values appropriately.
Jon Skeet
A: 

Get the class and dig the values with Class.getEnumConstants() from it.

iny
+1  A: 

You could look into replacing the enums with the Type Safe Enum Pattern, which would allow you to implement an interface, with a values() method that returned all the values for a particular implementation.

MHarris