2013-02-20 92 views
4

如果我有一堆類都包含一個Enum和EnumMap,我想爲這些類創建一個超類。創建一個通用類型的EnumMap枚舉

public interface ColorEnum { 
} 

class ColorMarbles extends Toy { 
    enum MARBLE implements ColorEnum 
     { BLUE, GREEN } 
    EnumMap<MARBLE, String> names = new EnumMap<MARBLE, String>(MARBLE.class); 
    //stuff 
    // fields 

    public void populate(ArrayList<String> designer) { 
     int i = 0; 
     for(MARBLE marble : MARBLE.values()) { 
      marble.name = designer.get(i); 
      i++; 
     } 
    } 
} 

class ColorBalloons extends Toy { 
    enum BALLOON implements ColorEnum 
     { YELLOW, RED } 
    EnumMap<BALLOON, String> names = new EnumMap<BALLOON, String>(BALLOON.class); 
    //stuff 
    // fields 

    public void populate(ArrayList<String> designer) { 
     int i = 0; 
     for(BALLOON balloon : BALLOON.values()) { 
      balloon.name = designer.get(i); 
      i++; 
     } 
    } 
} 

如何使創建一個超類具有泛型EnumMap,其中包含ColorEnum類型的枚舉像這樣?

public abstract class Toy { 
    EnumMap<ColorEnum, String> names; 
} 

eidt:我意識到我對我的例子太模糊了。狗可能是一個壞榜樣。我把它改成希望更清楚的東西。

我所擁有的是一堆類,其中包含填充EnumMap的填充方法。名稱按照預定義的順序排列。我希望能夠將它帶入Toy超類,而不是在每個新類類型的Toy中都複製粘貼。

希望這將解釋更多我在找什麼。

+0

我不確定你在做什麼。你能把它清理一下嗎? – 2013-02-20 16:13:28

+0

爲什麼不簡單地使用HashMap? EnumMap只是一個針對枚舉的優化實現。 – 2013-02-20 16:15:40

+0

我仍然無法在這裏清楚地看到這個意圖。在哪裏和誰被實際稱爲'populate()'方法?他們爲什麼不能簡單地靜止?你是否期望在運行時使用不同的值多次調用它們(從而更改名稱)?大理石和氣球的「設計師」名單是否相同,這意味着藍色大理石和黃色氣球具有相同的名稱或完全不相關?對不起,有這麼多問題,但我仍然不明白爲什麼簡單的枚舉方法不能在這裏工作。 :) – Natix 2013-02-20 17:09:52

回答

5

我有一種感覺,你的設計不必要的過於複雜。

使用枚舉

如果你不需要一個類繼承,你可以用枚舉工作直接與頂級類。

public interface Animal {} 

public enum Dog implements Animal { 
    HUSKY("Husky"), LAB("Labrador"); 

    private final String name; 

    Dog(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return name; 
    } 
} 

枚舉可以像任何其他Java類一樣聲明字段,方法和實現接口。他們唯一的限制是他們的直接超類總是java.lang.Enum,他們不能被擴展。

但是每個枚舉常量都可以擁有自己的一組傳遞給它的構造函數的唯一數據。甚至有可能每個常量都可以通過其獨特的實現覆蓋該枚舉的常見方法。

一個很好的教程解釋更多關於枚舉的全功率: http://javarevisited.blogspot.cz/2011/08/enum-in-java-example-tutorial.html


不枚舉

如果你需要一個實際的類繼承從共享一些通用的方法(例如Animal超類),我仍然會放棄地圖方法,而是嘗試更多面向對象的操作:

public class Animal { 
} 

public abstract class Dog extends Animal { 

    public abstract String getName(); 

    public static class Husky extends Dog { 
     @Override 
     public String getName() { 
      return "husky"; 
     } 
    } 

    public static class Lab extends Dog { 
     @Override 
     public String getName() { 
      return "labrador"; 
     } 
    } 

} 
+2

您也可以將'getName()'推送到接口。 – Zutty 2013-02-20 16:21:59

+0

我在每個類中都有完全相同的方法,並且細化了所有我想創建可以容納所有泛型方法的抽象超類的類。但要做到這一點,我需要訪問EnumMap。 – Aboutblank 2013-02-20 16:27:34

+0

也許我實際上並沒有幫助你解決問題,但這是我可以從你的狗的名字中得到的所有東西。也許你應該讓你的問題更具體地說明你想要達到的目標。 – Natix 2013-02-20 16:39:54

1

我用於這種事情的一種機制是擴展一個通用基類,它具有一個通用參數,允許您將Enum的詳細信息傳遞給它。

這個例子定義了一個基礎Table類數據庫表:

public class Table<Column extends Enum<? extends Column>> { 
    // Name of the table. 
    protected final String tableName; 
    // All of the columns in the table. This is actually an EnumSet so very efficient. 
    protected final Set<Column> columns; 

    /** 
    * The base interface for all Column enums. 
    */ 
    public interface Columns { 
    // What type does it have in the database? 
    public Type getType(); 
    } 

    // Small list of database types. 
    public enum Type { 
    String, Number, Date; 
    } 

    public Table(String tableName, 
       Set<Column> columns) { 
    this.tableName = tableName; 
    this.columns = columns; 
    } 

} 

現在你可以繼承這一點:

public class VersionTable extends Table<VersionTable.Column> { 

    public enum Column implements Table.Columns { 
    Version(Table.Type.String), 
    ReleaseDate(Table.Type.Date); 

    // Sadly all of this must be in ALL of your enums but most of the work can be pushed up to `Table` 
    final Table.Type type; 

    Column(Table.Type type) { 
     this.type = type; 
    } 

    @Override 
    public Type getType() { 
     return type; 
    } 
    } 

    public VersionTable() { 
    super("Versions", EnumSet.allOf(Column.class)); 
    } 
} 

,並在處理您的枚舉父類使用功能。

請注意,我將EnumSet傳遞給Table構造函數。如果您決定EnumSet不足,我相信您可以更改此以適應您的EnumMap要求。

+0

一個聰明的模式,但我有點關心類型命名:'Columns'是'Table'中的嵌套接口,其中'Column'是範圍中定義的類型變量通用Table類的類。爲了避免混淆,我會將聲明更改爲'class Table >'。 – Natix 2013-02-20 16:47:14

+0

@Natix - 雖然我很長時間並且很難確定命名,並且考慮了當前通用類型的單字母大寫字母的方法。通過一切手段選擇你喜歡的任何命名約定。在我使用大約十幾張表格的環境中,「列」/「列」對我來說最自然,並且沒有混淆。很明顯,你會看到強大的類型檢查的巨大好處,同時仍然只能編寫大部分的樣板代碼。 – OldCurmudgeon 2013-02-20 22:31:54

相關問題