Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I require a generic parameter to be an enum that implements an interface?

I'm not 100% convinced that this is a good idea, but I bumped into some code today that's currently implemented as:

class MyWidget <T extends Enum<T> > {   MyWidget(Map<T, Integer> valueMap) {     mValueMap = valueMap;   }    Map<T, Integer> mValueMap; } 

where MyWidget then offers methods that use mValueMap to convert the passed-in Enum to/from an Integer.

What I was considering doing was trying to refactor this, so that I'd declare my enumeration:

interface MyInterface {   public Integer getValue(); }  enum MyEnum implements MyInterface {   foo, bar;   public Integer getValue() {     return ordinal();   } } 

And I'd then be able to rewrite MyWidget into something that looked vaguely like this:

public class MyWidget<T extends Enum<T> extends MyInterface> {   ... } 

and would then be able to call the getValue() method from MyInterface on T-type objects within MyWidget. The problem, of course, is that "<T extends Enum<T> extends MyInterface>" isn't valid syntax. Is there any way to pull this off?

I don't want to just have MyWidget<T extends MyInterface>, because it's also important that T be an enumeration.

Thanks in advance!

like image 840
Sbodd Avatar asked Jul 01 '09 18:07

Sbodd


People also ask

Can an enum implements an interface?

Yes, Enum implements an interface in Java, it can be useful when we need to implement some business logic that is tightly coupled with a discriminatory property of a given object or class.

Can enums be generic?

However, it is possible to use enums in generics. The MSDN article for Enum gives the following type definition for the class Enum . This definition can be used to get enum s working as generic types by constraining the generic type to those of Enum .

How do you define an enum in an interface?

To make it clearer, please see the following code: public interface Thing{ public enum Number{ one(1), two(2), three(3); private int value; private Number(int value) { this. value = value; } public int getValue(){ return value; } } public Number getNumber(); public void method2(); ... }


1 Answers

Use an '&' instead:

public class MyWidget<T extends Enum<T> & MyInterface> {     ... } 

The JLS calls this an "intersection type", but I can find no mention of it in the Java tutorials. I'll just say that it does exactly what you were wishing that "extends" would do.

Also, I should mention that you can have as many types as you want in the intersection type. So if you wanted, you could do:

public class MyWidget<T extends Enum<T> & MyInterface & Serializable & Cloneable> {     ... } 

[Note: this code sample should not be construed as an endorsement of the Cloneable interface; it was merely handy at the time.]

like image 90
Michael Myers Avatar answered Oct 05 '22 14:10

Michael Myers