I have two enums that implement a common interface. I've tried to declare the interface so only enums can implement it.
interface CommonEnumInterface<E extends Enum<?>> {
/** It doesn't matter what this does. */
E commonInterfaceMethod();
}
enum Enum1 implements CommonEnumInterface<Enum1> {
FOO,
BAR,
BAZ;
@Override
public Enum1 commonInterfaceMethod() {
return null;
}
}
enum Enum2 implements CommonEnumInterface<Enum2> {
BLAH,
YADDA,
RHUBARB;
@Override
public Enum2 commonInterfaceMethod() {
return Enum2.BLAH;
}
}
Now I want to create another enum, where each constant has its own Set of elements of type CommonEnumInterface
, but not necessarily the same class. Every way I've found feels like a hack, though, especially for cases where I want each constant to declared with more than one set of elements.
These comments show what I've tried. Is there a more elegant way (that compiles)?
enum CreatingAnotherEnumAttempt {
// Type mismatch: cannot convert from List<Enum<?>&CommonEnumInterface<?>> to List<CommonEnumInterface<?>>
A(Arrays.asList(Enum1.FOO, Enum2.BLAH)),
// Cannot cast from List<Enum<?>&CommonEnumInterface<?>> to List<CommonEnumInterface<?>>
B((List<CommonEnumInterface<?>>) Arrays.asList(Enum1.FOO, Enum2.BLAH)),
// This works, but it generates type safety warnings, and it's hard to read.
C(Arrays.asList((CommonEnumInterface<?>) Enum1.FOO, (CommonEnumInterface<?>) Enum2.BLAH)),
// This is the best I've come up with.
D(getMixOfElements(Enum1.FOO, Enum2.BLAH));
/**
* I want to populate this set in the constructor.
*/
private final Set<CommonEnumInterface<?>> mixOfElements;
/**
* I tried declaring the Set this way, but wildcards can extend only one interface, so there's a syntax error at the ampersand.
*/
private final Set<? extends Enum<?> & CommonEnumInterface<?>> mixOfElements;
/**
* This is the constructor I'm trying to satisfy.
*
* @param mixOfElements I could make this a varargs parameter, but that only works for a single set of elements. What if I want more?
*/
private CreatingAnotherEnumAttempt(List<CommonEnumInterface<?>> mixOfElements) {
this.mixOfElements = Collections.unmodifiableSet(new HashSet<CommonEnumInterface<?>>(mixOfElements));
}
/**
* This method only exists to allow method {@link #D}. It's pretty pointless, otherwise.
*
* @param mixOfElements the mix of elements
* @return the mix of elements as a list
*/
private static List<CommonEnumInterface<?>> getMixOfElements(CommonEnumInterface<?>... mixOfElements) {
return Arrays.asList(mixOfElements);
}
/**
* This works without type safety warnings or superfluous methods, but for my constructor, I need a one-liner.
*/
private static void wayThatWorksInline() {
Collection<CommonEnumInterface<?>> inlineWay = new ArrayList<CommonEnumInterface<?>>();
inlineWay.add(Enum1.FOO);
inlineWay.add(Enum2.BLAH);
}
}
My question is above, and in the code comments. Generally, is this the right way to declare my interface?