Java 如何在没有实现的情况下向公共API公开枚举?
我有一个类,它有一个类型为枚举的属性。例如:Java 如何在没有实现的情况下向公共API公开枚举?,java,api,enums,api-design,Java,Api,Enums,Api Design,我有一个类,它有一个类型为枚举的属性。例如: 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
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
enum。CarType
enum可能包含我不想公开/发布的其他属性和方法(country
)
如果我想隐藏CarType
的实现,但我仍然想以某种方式公开可能的值(声明的枚举值),以便API用户可以在switch
和if
语句中引用它们,我该怎么办
ICar car = ...; // Get an instance somehow.
if (car.getType() == CarType.TOYOTA) System.out.println("It's Toyota.");
使附加属性和方法受保护
或私有
不是一个好的解决方案,因为这样库的其他部分也无法引用它们
如果我想继续使用enum,有什么好的替代方法来解决这个问题吗?
受保护的
,私有的
和包私有的
是为此提供的主要工具。如果您充分考虑您的类层次结构,您可能可以使用它们做一些事情
你应该考虑作文。拥有一个
TypeDetails
类,并让CarType
的每个成员都包含一个TypeDetails
成员。然后,您可以将对TypeDetails
getter的访问限制为只有那些在库的所有部分都可以看到TypeDetails
的同时应该访问它的人。如果必须将country
属性隐藏到用户代码中,您可以使用标准可见性(声明的属性没有public
、protected
或private
限定符,这些属性只对同一包中的类可见)。我希望这会有用,但我知道这只是一个补丁
无论如何,我无法完全理解您的设计和必要性,因此您可能没有其他选择,但如果您想保护代码不被API滥用,您可能需要重新设计并考虑封装问题。您可以为公共API提供枚举,并将其转换为另一个枚举以供私人使用。
例如,使用一个映射,其中键是公共枚举实例和值-私有枚举实例。
问题是每次调用API时都必须转换数据。可能需要在许多地方进行更改。尽管有一位后来的人想补充我的想法- 枚举还可以实现一个接口,在该接口中,您可以仅公开所需的详细信息:
public enum CarType implements ICarType {
...
public String getTypeName(){
return name();
}
}
public interface ICarType {
public String getTypeName();
}
所以您计划在if()/switch中使用它
问题中提到的问题是,枚举是从库的多个包中使用的,因此无法降低附加属性和方法的可见性。也许可以尝试使用getter方法公开属性,甚至返回防御副本,以防滥用?如果不是这样的话首先,我担心您需要重新设计您的库,严格区分API用户可见的私有逻辑和公共DTO。该属性只是一个示例(比方法短),但同样的可见性也适用于方法。最初的问题来自我想使用枚举,而枚举无法扩展您自己的类。使用类层次结构,这不会是一个问题(我可以发布祖先类并将子类隐藏在公共API中)。枚举是从库的多个包中使用的,因此我无法降低可见性。这意味着组合也不是一个好的解决方案(因为它使用受限访问)。我之所以接受这个答案,是因为我提到我希望它作为枚举发布,没有其他方法。尽管我选择了另一条路径,因为我想公开一些附加功能(但不是全部),显然不希望复制附加功能。相反,我将枚举公开为接口,其中我要发布的附加功能是接口的一部分,枚举常量也列为接口常量。此解决方案还避免了进行转换和更改实现。
ICarType carType; //Not referencing the enum
if("TOYOTA".equalsIgnoreCase(carType.getTypeName())){
print("Toyota....");
}