抽象类中的枚举



我想弄清楚如何在不同的类中使用枚举扩展一个共同的抽象类。

简单的例子:


卡类

public class Card {
    private String name;
    private String value;
    private String suit;
   public Card(String name, String value, String suit) {
        this.value = value;
        this.suit= suit;
    }
}

抽象DECK类

public abstract class Deck {
    private enum SUITS{
    }
    private enum VALUES{
    }
    private int cardNumber;
    private ArrayList<Card> cardList;
    public Deck(VALUES valori,SUITS semi){
        ArrayList<Card> clist = new ArrayList<>();
        for (SUITS s: semi.values()){
            for (VALUES v: valori.values()){
                cardList.add(new Card(v.toString(),s.toString()));
            }
        }
        cardNumber = cardList.size();
    }

类BriscolaDeck

public class CarteBriscolaDeck extends Deck {
   private enum SUITS{
        COPPE,
        DENARE,
        BASTONI,
        SPADE
    }
    private enum VALUES{
        ASSO,
        DUE,
        TRE,
        QUATTRO,
        CINQUE,
        SEI,
        SETTE,
        FANTE,
        CAVALLO,
        RE
    }
    public CarteBriscolaDeck(){
        super(VALUES,SUITS);
    }
}

类PokerDeck

public class PokerDeck extends Deck {
   private enum SUITS{
       SPADES,
       HEARTS,
       DIAMONDS,
       CLUBS
   }
    private enum VALUES{
        ACE,
        TWO,
        THRRE,
        FOUR,
        FIVE,
        SIX,
        SEVEN,
        EIGHT,
        NINE,
        TEN,
        JACK,
        QUEEN,
        KING
    }
    public PokerDeck(){
        super(VALUES,SUITS);
    }
}

我做的对吗?是否有可能进行优化?

提前感谢。

您不能在基类中声明enum以被子类覆盖,因为enum总是隐式地final。而且,子类enum s不能扩展任意类型,它们总是隐式地扩展java.lang.Enum

你能做的,是在基类中声明interface,子类enum将实现。但是,由于您没有在枚举中指定任何可以抽象的功能,因此这样做(目前)没有意义。另一种方法是为基类指定类型参数,子类将用它们的实际类型填充这些参数。

另一件需要修复的事情是,在Card类中使用"suite"one_answers"value"类型而不是String s,因为在那里使用字符串会破坏使用enum s的全部优势。

public final class Card<S,V> {
    final S suit;
    final V value;
    public Card(S suit, V value) {
        this.suit = suit;
        this.value = value;
    }
    @Override
    public String toString() {
        return suit+" "+value;
    }
}
public class Deck<S extends Enum<S>,V extends Enum<V>> {
    protected final Set<S> allSuits;
    protected final Set<V> allValues;
    protected final List<Card<S,V>> allCards;
    public Deck(Class<S> suitType, Class<V> valueType) {
        Set<S> suits =EnumSet.allOf(suitType);
        Set<V> values=EnumSet.allOf(valueType);
        List<Card<S,V>> cardList=new ArrayList<>(suits.size()*values.size());
        for(S suite: suits){
            for(V value: values) {
                cardList.add(new Card<>(suite, value));
            }
        }
        allSuits =Collections.unmodifiableSet(suits);
        allValues=Collections.unmodifiableSet(values);
        allCards =Collections.unmodifiableList(cardList);
    }
    @Override
    public String toString() {
        return getClass().getSimpleName()+allCards;
    }
}
public class PokerDeck extends Deck<PokerDeck.Suits,PokerDeck.Values> {
    enum Suits  { SPADES, HEARTS, DIAMONDS, CLUBS }
    enum Values { ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN,
                  EIGHT, NINE, TEN, JACK, QUEEN, KING }
    public PokerDeck(){
        super(Suits.class, Values.class);
    }
}
public class CarteBriscolaDeck
       extends Deck<CarteBriscolaDeck.Suits,CarteBriscolaDeck.Values> {
    enum Suits  { COPPE, DENARE, BASTONI, SPADE }
    enum Values { ASSO, DUE, TRE, QUATTRO, CINQUE, SEI, SETTE, FANTE, CAVALLO, RE }
    public CarteBriscolaDeck(){
        super(Suits.class, Values.class);
    }
}

我觉得不合适。我不明白你为什么要在这里使用Enum。Collection也可以做同样的事情,而且对读者来说更清晰。

您可以在枚举中有一个带标志的构造函数,并将相关值传递给父方法。过滤可以使用SUIT_TYPS来完成。一个或SUIT_TYPES。2

public enum SUITS {
    COPPE(SUIT_TYPES.ONE.name()),
    DENARE(SUIT_TYPES.ONE.name()),
    BASTONI(SUIT_TYPES.ONE.name()),
    SPADE(SUIT_TYPES.ONE.name()),
    SPADES(SUIT_TYPES.TWO.name()),
    HEARTS(SUIT_TYPES.TWO.name()),
    DIAMONDS(SUIT_TYPES.TWO.name()),
    CLUBS(SUIT_TYPES.TWO.name());
    private final String type;
    SUITS(String type) {
        this.type = type;
    }
    public String getType() {
        return type;
    }
}
enum SUIT_TYPES {
    ONE, TWO
}

可没那么容易。你在子类中声明了全新的类型;因此,没有像您希望的那样隐含的"重写"。您可以看到,基类构造函数接受两个类型为Deck的枚举。西装,…传入一个类型为Poker的enum。套装不能用

一种方法是使用泛型:
abstract class Deck<S extends Enum<S>, V extends Enum<V>> {
  abstract protected List<S> getSuiteEnums();
  abstract protected List<V> getValuesEnums();
  public Deck(){
    ArrayList<Card> clist = new ArrayList<>();
    for (S s: getSuiteEnums()){
    ...
}

,然后在子类中:

public class PokerDeck extends Deck<PokerDeck.POKERSUITES, PokerDeck.POKERVALUES> {
  enum POKERSUITS { SPADES, ..
  enum POKERVALUES { ...
  @Override 
  protected List<POKERSUITS> getSuiteEnum() { 
    return list with POKERSUITES.values()); 

请注意:这是更多的"伪代码"风格;所以请原谅我的错别字。来制作扑克牌。POKERSUITS工作,内部枚举也不能是私有的。我在这里选择使用抽象方法,因为它们有助于实现开/闭原则。

所以,长话短说:是的,这可以通过使用在子类中声明的enum来实现。但是说实话;我没有看到在这里使用枚举的附加价值。你不妨这样写:
abstract protected List<String> getSuiteNames();

并在每个子类中轻松实现:

return Arrays.asList("SPADES", "

In Desk constructor:

public Desk(Object[] values, Object[] suits)

在子类中:

public Subclass(){ 
    super(values.values(), suits.values()) 
}

最新更新