2014-01-24 57 views
3

我有一個類,它有一個類型爲Enum的屬性。例如:如何在沒有實現的情況下將枚舉暴露給公共API?

enum CarType { 
    TOYOTA("Japan"), 
    AUDI("Germany"), 
    BMW("Germany"); 

    public final String country; 
    private CarType(String country) { this.country = country; } 
} 

class Car { 
    private CarType type; 
    public CarType getType() { return type; } 
} 

Car是一個庫的一部分,我想揭露它的功能,所以我創建這將是公共API的一部分接口,並有一流的Car實現它:

interface ICar { 
    CarType getType(); 
} 

class Car implements ICar { 
    private CarType type; 
    @Override public CarType getType() { return type; } 
} 

這種方法的問題是,這將需要發佈整個CarType枚舉。 CarType枚舉可能包含我不想公開/發佈的其他屬性和方法(本例中爲country)。

我能做些什麼,如果我想隱藏的CarType的實現,但我還是想在某種程度上暴露的可能值(聲明枚舉值),從而使API用戶可以在switch引用它們和if陳述這樣:

ICar car = ...; // Get an instance somehow. 
if (car.getType() == CarType.TOYOTA) System.out.println("It's Toyota."); 

製作的附加屬性和方法protectedprivate是不是一個很好的解決方案,因爲該庫的那麼其他部分也將不能引用他們。

如果我想繼續使用Enums,有沒有什麼好的替代方案來解決這個問題?

回答

1

你可以爲公共API提供Enum,並將其轉換爲另一個Enum以供私人使用。
例如使用一個Map,其中鍵是public Enum實例和值 - 私有Enum實例。
問題是每次調用API時都必須轉換數據。可能需要在很多地方進行更改。

+0

我接受這個答案,因爲我提到我希望它以enum的形式發佈,並且沒有其他方法可以實現它。雖然我走了一條不同的道路,因爲我想公開一些附加功能(但不是全部),並且顯然不希望複製附加功能。相反,我將枚舉公開爲接口,其中我想發佈的附加功能是接口的一部分,枚舉常量也列爲接口常量。該解決方案還避免了必須進行轉換和實施更改。 – icza

0

protected,privatepackage-private是您爲此提供的主要工具。如果你足夠考慮你的班級結構,你可以使用它們做一些事情。

你應該考慮構圖。有一個TypeDetails類,並且CarType的每個成員都包含一個TypeDetails成員。然後,您可以限制訪問TypeDetails獲取者,只允許那些應該訪問該訪問者的人員訪問它,同時讓TypeDetails本身對庫的所有部分可見。

+0

enum從庫的多個包中使用,所以我無法降低可見性。這意味着構圖也不是一個好的解決方案(因爲它使用受限訪問)。 – icza

0

如果是絕對必要隱藏country屬性用戶代碼,你可以去標準能見度(聲明沒有publicprotectedprivate預選賽,這些屬性只能是在同一個包類可見屬性)。我希望這是有用的,但我知道這只是一個補丁。

反正我不能完全理解你的設計和必需品,所以也許你沒有其他選擇,但也許你需要的是在考慮封裝了重新設計,如果你想保護你的代碼API濫用

+0

問題中提到的問題是,enum是從庫的多個包中使用的,因此無法減少其他屬性和方法的可見性。 – icza

+0

也許代替這個,你可以嘗試用getter方法暴露屬性,甚至返回防禦性副本來防止濫用?如果這是不可能的,那麼恐怕您需要重新設計您的庫,並嚴格劃分私有邏輯和API用戶可見的公共DTO。 –

+0

該屬性只是一個示例(它比方法短),但同樣的可見性也適用於方法。原來的問題來自我想使用枚舉和枚舉不能擴展你自己的類。使用類層次結構,這不會是一個問題(我可以發佈祖先類,並保持從公共API隱藏子類)。 – icza

1

雖然晚了一個想加入我的想法 -

枚舉也可以實現一個接口,在那裏你可以僅露出需要細節:

public enum CarType implements ICarType { 
    ... 
     public String getTypeName(){ 
     return name(); 
     } 
    } 

    public interface ICarType { 
     public String getTypeName(); 
    } 

所以,你的計劃如果(使用它在)/ switch

ICarType carType; //Not referencing the enum 

    if("TOYOTA".equalsIgnoreCase(carType.getTypeName())){ 
    print("Toyota...."); 
    } 
相關問題