我有两个实现通用接口(interface)的枚举。我尝试声明该接口(interface),以便只有枚举可以实现它。
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;
}
}
现在我想创建另一个枚举,其中每个常量都有自己的 CommonEnumInterface
类型的元素集,但不一定是同一个类。不过,我发现的每一种方法都感觉像是一种黑客攻击,特别是在我希望每个常量都用多个元素集声明的情况下。
这些评论显示了我已经尝试过的内容。有没有更优雅的方式(编译)?
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);
}
}
我的问题在上面,在代码注释中。一般来说,这是声明我的接口(interface)的正确方法吗?
最佳答案
涉及枚举的事实实际上是一种转移,因为只需传递 List<CommonEnumInterface<?>>
进入构造函数是你的目标。为此,请执行以下操作:
A(Arrays.<CommonEnumInterface<?>>asList(Enum1.FOO, Enum2.BLAH)),
//etc.
问题是类型推断 - 有时它有点太急切了。基于论据Enum1.FOO
和Enum2.BLAH
至asList
,编译器推断 Enum<?>&CommonEnumInterface<?>
对于 T
,等等 List<Enum<?>&CommonEnumInterface<?>>
被退回。自 generics aren't covariant ,这不能分配给 List<CommonEnumInterface<?>>
。指定 T
的类型参数手动解决此问题。
关于java - 使用通用接口(interface)实例化枚举集合的单行代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21035711/