2014-04-19 66 views
1

我在Eclipse中使用Java,和我讀了thread默認情況下Checkstyle中不允許使用受保護的變量,但在枚舉中怎麼辦?

我真的很喜歡home'sanswer,因爲我從來沒有想過這件事。子類的整個想法實際上不應該訪問那些成員。不過,如果有人想放棄它,我會有一個有趣的邊緣案例。

假設我有一個接口Buildable和枚舉CatanPiece

public interface Buildable 
{ 
    HashMap<Resource, Integer> getCost(); 
    Buildable build(final PlayerHand payment); 
} 

public enum CatanPiece implements Buildable 
{ 
    ROAD 
    { 
     @Override 
     public HashMap<Resource, Integer> getCost() 
     { 
      if (cost.isEmpty()) 
      { 
       cost.put(BRICK, 1); 
       cost.put(LUMBER, 1); 
      } 
      return cost; 
     } 
    }, 

    SETTLEMENT 
    { 
     @Override 
     public HashMap<Resource, Integer> getCost() 
     { 
      if (cost.isEmpty()) 
      { 
       cost.put(BRICK, 1); 
       cost.put(LUMBER, 1); 
       cost.put(SHEEP, 1); 
       cost.put(WHEAT, 1); 
      } 
      return cost; 
     } 
    }, 

    CITY 
    { 
     @Override 
     public HashMap<Resource, Integer> getCost() 
     { 
      if (cost.isEmpty()) 
      { 
       cost.put(WHEAT, 2); 
       cost.put(ORE, 3); 
      } 
      return cost; 
     } 
    }; 

    protected final HashMap<Resource, Integer> cost; 

    private CatanPiece() 
    { 
     cost = getCost(); 
    } 

    @Override 
    public abstract HashMap<Resource, Integer> getCost(); 

    @Override 
    public Buildable build(final PlayerHand payment) 
    { 
     return (payment.remove(cost) ? null : this); 
    } 
} 

所以Checkstyle的是給我約我使用受保護的HashMap的廢話,但對於那些在尋找這個問題說明白,你便可以看到我沒有人濫用這個變量的問題。我實際上將它設爲私有並使用受保護的get方法,但該方法的返回值在每個實例中都不相同。

可能的答案:忽略的CheckStyle警告,或者是包括摘要的init()方法來初始化HashMap的那麼只需執行getCost()方法一般爲枚舉的所有承包商,客人。

您認爲如何?

回答

2

Checkstyle對枚舉的理解有時是不完整的。我猜想VisibilityModifier檢查的作者沒有想到枚舉。枚舉是一個角落案例,需要一些額外的支票屬性。

然而,無意中,在你的情況下,警告仍然是正確的。我相信在Enum中不應該使用protected字段。如果你在你的Enum常量中需要特定於實例的狀態,通過構造函數或通過靜態初始化來初始化它。

請嘗試以下方法。這應該帶給你幾個好處:

  • Checkstyle警告消失,因爲Map現在是private
  • CatanPiece枚舉常量現在確實是常量,因爲成本映射是不可變的。
  • 沒有延遲初始化的開銷。 CatanPiece枚舉常量的用戶可以確定費用映射已正確初始化。

唯一的缺點是每當Enum被擴展時(例如SHIP),開發者不能忘記更新buildCostMap()。但是這樣的錯誤會很快顯示出來。

public enum CatanPiece implements Buildable 
{ 
    ROAD, SETTLEMENT, CITY; 

    private static final Map<CatanPiece, Map<Resource, Integer>> allCosts = 
      buildCostMap(); 

    private static Map<CatanPiece, Map<Resource, Integer>> buildCostMap() 
    { 
     Map<CatanPiece, Map<Resource, Integer>> result = 
      new HashMap<CatanPiece, Map<Resource, Integer>>(); 

     Map<Resource, Integer> cost = new EnumMap<Resource, Integer>(Resource.class); 
     cost.put(Resource.WHEAT, 2); 
     cost.put(Resource.ORE, 3); 
     result.put(CITY, Collections.unmodifiableMap(cost)); 

     cost = new EnumMap<Resource, Integer>(Resource.class); 
     cost.put(Resource.BRICK, 1); 
     cost.put(Resource.LUMBER, 1); 
     cost.put(Resource.SHEEP, 1); 
     cost.put(Resource.WHEAT, 1); 
     result.put(SETTLEMENT, Collections.unmodifiableMap(cost)); 

     cost = new EnumMap<Resource, Integer>(Resource.class); 
     cost.put(Resource.BRICK, 1); 
     cost.put(Resource.LUMBER, 1); 
     result.put(ROAD, Collections.unmodifiableMap(cost)); 

     return Collections.unmodifiableMap(result); 
    } 

    @Override 
    public Map<Resource, Integer> getCost() { 
     return allCosts.get(this); 
    } 

    @Override 
    public Buildable build(final PlayerHand payment) { 
     return payment.remove(cost) ? null : this; 
    } 
} 
+0

太棒了!好主意@托馬斯!這非常有幫助。大量使用Collections類方法'unmodifiableMap'。 我非常喜歡這個解決方案。根據定義,Enum應該永遠不需要那麼做,所以我可以吞下那個藥片。 – aaiezza

相關問題