2016-09-14 99 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