2014-01-24 56 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...."); 
    } 
相关问题