Search code examples
javainterfaceenumstype-constraints

Enum<? extends interface>


I'm attempting to have a collection of enums that extend a common interface, so something like:

interface Fooable
{
  void someCommonMethod();
}

enum E1 implements Fooable
{
   // some enumuerations and a definition for someCommonMethod()
}

enum E2 implements Fooable
{
   // some different enumerations and a different definition for someCommonMethod()
}

and then make use of this elsewhere by enforcing both that a variable is a Enum and implements the interface. So something along the lines of..

bar(Enum<? extends Fooable> fe)
{
  fe.ordinal();
  fe.someCommonMethod();
}

However, so far I seem to have to cast fe in order to treat it as implementing the interface, i.e.,

bar(Enum<? extends Fooable> fe)
{
  fe.ordinal();
  ((Fooable)fe).someCommonMethod();
}

and while this should be safe... it seems suboptimal and that I may be overlooking something. Of course if I try to just pass the param as a Fooable then I wind up casting to treat it as a Enum and not only is this no-gain I'm now not even safe. See following:

bar(Fooable fe)
{
  // potentially unsafe cast!
  ((Enum<?>)fe).ordinal();
  fe.someCommonMethod();
}

Is there anything I'm overlooking or is the

Enum<? extends Fooable>

about as close to a 'good' solution as I'll get?

I am relatively new to Java and am still catching myself trying to use it like C or C++ so if I'm treating it like a hammer instead of a saw or overlooking something stupidly simple feel free to point it out :)


Solution

  • One option you have is to add any of the methods from Enum you need onto Fooable or create a new interface that extends Fooable and adds the Enum methods you need.

    Example:

    interface Fooable {
       void someCommonMethod();
    }
    
    interface FooableEnum extends Fooable {
       int ordinal();
    }
    
    enum E1 implements FooableEnum {
       // Implement someCommonMethod.
       // ordinal() is already implemented by default.
    }
    

    Once you've done this you can use FooableEnum as the parameter type in your method signature and not worry about any of the generic stuff.