【问题标题】:How do you properly extend/subclass EnumSet in Java?如何在 Java 中正确扩展/继承 EnumSet?
【发布时间】:2014-10-11 19:46:44
【问题描述】:

我尝试扩展 EnumSet 以在 Eclipse 中实现 Comparable。然而,我从一开始就充满了错误。这是我的开始:

package sets;

import java.util.EnumSet;


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

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

}

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

它立即通知我:Implicit super constructor EnumSet&lt;Suits&gt;() is undefined for default constructor. Must define an explicit constructor. 所以,我按照快速修复并添加了以下构造函数:

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

...然后它通知我:The constructor EnumSet&lt;Suits&gt;(Class&lt;E&gt;, Enum[]) is not visible。我已经尝试更改此类和此构造函数的访问修饰符,但无济于事。

(问题 2)重写抽象方法

下一个问题是当我决定继续并修复 Eclipse 报告的下一个错误时:The type ExtendedEnumSet must implement the inherited abstract method AbstractCollection&lt;Suits&gt;.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;
}

然后报告The method addAll() of type ExtendedEnumSet must override or implement a supertype method。它为addRangecomplement 回显此错误。我可以从Set 复制addAll 签名:public boolean addAll(Collection&lt;? extends Suits&gt; collection)。但是,当我尝试从 API 文档复制其他方法签名(addRangecomplement)时,它们似乎不存在。我很茫然。

我改用EnumMap,效果很好。 EnumSet 似乎是不可能的。我错过了什么吗?

【问题讨论】:

  • 您最好只使用Comparator&lt;EnumSet&lt;Foo&gt;&gt; 而不是尝试扩展它。
  • 您的意思是implements Comparable&lt;EnumSet&lt;Suits&gt;&gt;,还是您想比较西装本身?如果是后者,你应该创建一个实现Comparator&lt;Suits&gt;的类。
  • 为什么你认为你需要扩展EnumSet来实现Comparable&lt;Suits&gt;?将EnumSet&lt;Suits&gt;Suits 进行比较是什么意思?假设我有一组 { SPADE, HEART } 并将其与 Club 进行比较? compareTo 会返回什么?
  • 我需要它是Comparable,所以我可以将它存储在TreeSet中。
  • @skia.heliou:不,你没有。您可以将Comparator 传递给TreeSet 构造函数;你不需要它是Comparable,只是把它放在TreeSet中。

标签: java constructor subclass extends enumset


【解决方案1】:

简短回答:EnumSet 并非旨在扩展至 java.util 包之外。

长答案:EnumSet 有两个实现:MiniEnumSetHugeEnumSet。迷你版被优化为使用单个long 来表示值;巨大的使用多个多头。这些类“隐藏”在 JRE 中,因此调用代码不知道其中的区别。这就是 EnumSet 提供许多静态工厂方法来创建新实例的原因。这是防止脆弱基类反模式的常见设计模式。

编译器告诉您不能调用该类的超级构造函数,因为开发人员将其标记为 package-private。因此,您必须将代码打包在java.util 下才能调用它。与您尝试覆盖的其他方法相同。

【讨论】:

    【解决方案2】:

    我猜EnumSet 从未打算由用户定义的类进行扩展。查看此方法的签名:

    abstract void addAll();
    

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

    TL;DL:很遗憾,您不能使用自己的类扩展EnumSet,因为这是不可能的。

    【讨论】:

    • 这可能是包私有范围和 Eclipse 的问题,因为最终需要将原始抽象签名替换为 public boolean addAll(Collection&lt;? extends Suits&gt; collection)
    猜你喜欢
    • 2020-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-21
    • 2018-05-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多