2016-09-14 90 views
2

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

简单的例子:


卡类

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); 
    } 
} 

我这样做对吗?有没有可能优化?

预先感谢您。

+0

提示:请让我知道我的答案是否适合您;或者如果有什么你会寻找;否则考虑接受最适合的答案来表明“你有你需要的东西”。 – GhostCat

回答

0

这并不容易。你在你的子类中声明了全新的类型;所以没有像你希望的那样隐含的“压倒一切”。 您会发现,您的基类构造函数需要两个类型为Deck.SUITS的枚举,因此传入类型为Poker.SUITS的枚举不起作用。围绕

的一种方法是使用泛型:

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()); 

请注意:这是更多的“伪代码”的风格;所以原谅错别字等。为了使PokerDeck.P​​OKERSUITS发挥作用,该内部枚举也是不公开的。而且:我选择在这里使用抽象方法,因为他们帮助Open/Closed principle

因此,长话短说:是的,这可以通过使用子类中声明的枚举来完成。但说实话;我没有看到在那里使用枚举的附加价值。你不妨有:

abstract protected List<String> getSuiteNames(); 

每个子类中实现,很容易为:

return Arrays.asList("SPADES", " 
+1

您没有看到用于表示少量预定义值的枚举的优点吗?比较更快,类型检查更紧密。 OP的真正问题是'Card'字段是字符串而不是那些枚举的实例。 – RealSkeptic

+0

也许人们不得不再坐20分钟才能找到一个基于枚举的解决方案,以便在这里使用它们;也为子类化工作。但说实话:我已经在这里度过了相当长的一段时间。没有任何“回报”...所以,不知道,如果这将很快发生。 – GhostCat

0

我不认为这是我suitable.And不明白你为什么要使用在这里枚举。 一个集合可以为读者做同样的事情和更清晰。

-2

在台构造:

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

在子类:

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

我想你或者不熟悉枚举的概念,或者你的答案是不清楚如何使用数组而不是枚举,在这种情况下,你应该改进它。 – RealSkeptic

0

你可以在同一个标​​志,你的枚举构造,并通过相关的值,以超级方法。可以使用SUIT_TYPS.ONE或SUIT_TYPES进行过滤。二

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 
} 
1

你不能声明在基类的enum由子类覆盖,如enum s为总是隐final。此外,子类'enum s不能扩展任意类型,它们总是隐式扩展java.lang.Enum

你可以做什么,在子类'enum将实现的基类中声明interface。但是由于您没有在枚举中指定任何可以抽象的功能,因此没有必要这么做。另一种方法是为基类指定类型参数,子类将使用它们的实际类型进行填充。

另一件事来解决,是在你的Card类使用“套装”和“值”类型,而不是的String S,因为使用字符串有破坏使用enum S的整个优势。

E.g.

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); 
    } 
} 
+0

只是可以肯定...你写道: 保护最终设置 allsuits; 保护最终设置 allValues; 和之后 allSuits = Collections.unmodifiableSet(suit); allValues = Collections.unmodifiableSet(values); 是它的错字?因为最后意味着一个costant ..对吗? – tuffo19

+0

施工后无法修改'final'字段。但是,当然,他们必须在施工期间分配一次。在这里,它发生在构造函数的末尾,在收集完成后。 – Holger

+0

我明白了。但我的编译器(androidstudio)发送给我一个错误... – tuffo19