如何在Java中正确地扩展/子类化EnumSet?

4

我试图在Eclipse中扩展EnumSet以实现Comparable。然而,从一开始就遇到了很多错误。这是我的起点:

package sets;

import java.util.EnumSet;


enum Suits{
    SPADE, DIAMOND, CLUB, HEART;
}

class ExtendedEnumSet extends EnumSet<Suits> implements Comparable<Suits> {

}

(问题1)定义显式构造函数

这立即提示我:默认构造函数未定义棋牌套装枚举集的隐式超级构造函数。 必须定义一个显式构造函数。因此,我按照快速修复方法添加了以下构造函数:

ExtendedEnumSet(Class<Suits> finalArg0, Enum[] finalArg1) {
    super(finalArg0, finalArg1);
    // TODO Auto-generated constructor stub
}

...然后它告诉我:The constructor EnumSet<Suits>(Class<E>, Enum[]) is not visible。我尝试改变这个类和构造函数的访问修饰符也没有效果。

(问题2) 覆盖抽象方法

下一个问题是当我决定继续修复下一个Eclipse报告的错误时:The type ExtendedEnumSet must implement the inherited abstract method AbstractCollection<Suits>.iterator()。当然,这只是冰山一角。我再次使用快速修复(add unimplemented methods),它添加了以下内容:

@Override
public int compareTo(Suits finalO) {
    // TODO Auto-generated method stub
    return 0;
}

@Override
void addAll() {
    // TODO Auto-generated method stub

}

@Override
void addRange(Suits finalArg0, Suits finalArg1) {
    // TODO Auto-generated method stub

}

@Override
void complement() {
    // TODO Auto-generated method stub

}

@Override
public Iterator<Suits> iterator() {
    // TODO Auto-generated method stub
    return null;
}

@Override
public int size() {
    // TODO Auto-generated method stub
    return 0;
}

该错误信息为“类型ExtendedEnumSet的方法addAll()必须覆盖或实现一个超类型方法”,同时也会在addRange和complement中出现此错误。我可以从Set中复制addAll的签名:public boolean addAll(Collection<? extends Suits> collection)。然而,当我尝试从API文档中复制其他方法的签名(addRange、complement),它们似乎不存在。我感到很困惑。

我改用EnumMap,它运行良好。EnumSet似乎不可行。我有什么遗漏吗?


2
你最好只使用 Comparator<EnumSet<Foo>> 而不是试图扩展它。 - Louis Wasserman
1
你是想要实现Comparable<EnumSet<Suits>>,还是想要比较套装本身?如果是后者,你应该创建一个实现了Comparator<Suits>接口的类。 - Sean Van Gorder
1
为什么您认为需要扩展 EnumSet 来实现 Comparable<Suits>?将一个 EnumSet<Suits> 与一个 Suits 进行比较是什么意思?假设我有一个集合 { SPADE, HEART } 并将其与 Club 进行比较,compareTo 会返回什么? - David Conrad
我需要它是“可比较的”,这样我才能将其存储在“TreeSet”中。 - nikodaemus
1
@skia.heliou:不需要。你可以将一个“比较器”传递到“TreeSet”构造函数中;你不需要它是“可比较的”才能将其放入“TreeSet”中。 - Louis Wasserman
@LouisWasserman:好的,我可以做到。=)我只看了'add(E e)'方法而已。谢谢! - nikodaemus
2个回答

8
简短回答:EnumSet不适合在java.util包外进行扩展。
详细回答:EnumSet有两个实现:MiniEnumSet和HugeEnumSet。MiniEnumSet为使用单个long表示值进行了优化;HugeEnumSet使用多个longs。这些类被隐藏在JRE中,以便调用代码不知道差异。这就是为什么EnumSet提供了许多静态工厂方法来创建新实例。这是防止脆弱基类反模式的常见设计模式。
编译器告诉你不能调用类的超级构造函数,因为开发人员将其标记为包私有。因此,您必须将代码打包到java.util下才能调用它。对于您尝试覆盖的其他方法也是如此。

0

我猜测EnumSet从来没有被设计成可以被用户定义的类所扩展。请查看此方法的签名:

abstract void addAll();

这是一个抽象的概念,但它是包私有的,因此只有在同一包中的类才能看到(调用或覆盖)该方法。

TL;DL: 不幸的是,你不能使用自己的类扩展EnumSet,因为这是不可能的。


这可能与包私有作用域和Eclipse有关,因为原始的抽象签名最终需要替换为 public boolean addAll(Collection<? extends Suits> collection) - nikodaemus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接