我正在编写一个库,它有一组预定义的枚举值。 比方说,我的枚举如下所示。
public enum EnumClass {
FIRST("first"),
SECOND("second"),
THIRD("third");
private String httpMethodType;
}
现在使用此库的客户端可能需要添加更多值。假设客户需要添加CUSTOM_FIRST
和CUSTOM_SECOND
。这不会覆盖任何现有值,但会使枚举具有5个值。
在此之后,我应该能够使用类似<? extends EnumClass>
的东西来获得5种不变的可能性。
实现这一目标的最佳方法是什么?
答案 0 :(得分:40)
您不能enum
扩展另一个enum
,也不能通过继承“添加”现有enum
的值。
但是,enum
可以实现interface
。
我要做的是让原始enum
实现标记interface
(即没有方法声明),然后您的客户可以创建自己的enum
来实现相同的interface
}。
然后,您的enum
值会被他们的共同interface
引用。
为了加强要求,您可以让您的界面声明相关的方法,例如在你的情况下,public String getHTTPMethodType();
。
这会强制实现enum
来为该方法提供实现。
此设置与充足的API文档相结合,有助于以相对受控的方式添加功能。
自包含示例(不介意这里的懒名称)
package test;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<HTTPMethodConvertible> blah = new ArrayList<>();
blah.add(LibraryEnum.FIRST);
blah.add(ClientEnum.BLABLABLA);
for (HTTPMethodConvertible element: blah) {
System.out.println(element.getHTTPMethodType());
}
}
static interface HTTPMethodConvertible {
public String getHTTPMethodType();
}
static enum LibraryEnum implements HTTPMethodConvertible {
FIRST("first"),
SECOND("second"),
THIRD("third");
String httpMethodType;
LibraryEnum(String s) {
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
static enum ClientEnum implements HTTPMethodConvertible {
FOO("GET"),BAR("PUT"),BLAH("OPTIONS"),MEH("DELETE"),BLABLABLA("POST");
String httpMethodType;
ClientEnum(String s){
httpMethodType = s;
}
public String getHTTPMethodType() {
return httpMethodType;
}
}
}
<强>输出强>
first
POST
答案 1 :(得分:7)
枚举不可扩展。简单地解决您的问题
Enum.valueOf
:在静态地图中跟踪该类的所有实例例如:
public class MyType {
private static final HashMap<String,MyType> map = new HashMap<>();
private String name;
private String httpMethodType;
// replacement for Enum.valueOf
public static MyType valueOf(String name) {
return map.get(name);
}
public MyType(String name, String httpMethodType) {
this.name = name;
this.httpMethodType = httpMethodType;
map.put(name, this);
}
// accessors
public String name() { return name; }
public String httpMethodType() { return httpMethodType; }
// predefined constants
public static final MyType FIRST = new MyType("FIRST", "first");
public static final MyType SECOND = new MyType("SECOND", "second");
...
}
答案 2 :(得分:1)
将Enum当作具有静态最终实例的最终类来考虑。当然,您不能扩展最终类,但可以在库中将非最终类与静态最终实例一起使用。您可以在JDK中看到这种定义的示例。可以使用包含其他日志记录级别集的类来扩展java.util.logging.Level类。
如果您接受这种实现方式,则您的库代码示例可能类似于:
public class EnumClass {
public static final FIRST = new EnumClass("first");
public static final SECOND = new EnumClass("second");
public static final THIRD = new EnumClass("third");
private String httpMethodType;
protected EnumClass(String name){
this.httpMethodType = name;
}
}
客户端应用程序可以通过继承扩展静态成员列表:
public final class ClientEnum extends EnumClass{
public static final CUSTOM_FIRST = new ClientEnum("custom_first");
public static final CUSTOM_SECOND = new ClientEnum("custom_second");
private ClientEnum(String name){
super(name);
}
}
我认为该解决方案与您的要求很接近,因为所有静态实例都可以从客户端类中看到,并且它们都将满足您的通用通配符。
答案 3 :(得分:0)
我们通过这种方式修复了枚举继承问题,希望有所帮助
我们的应用程序有几个类,每个类都有很少的子视图(嵌套视图),为了能够在childViews之间导航并保存currentChildview,我们将它们保存为每个类中的枚举。 但我们不得不在每个枚举中复制粘贴,一些常见的功能,如next,previous等。 为了避免我们需要BaseEnum,我们使用interface作为基本枚举:
public interface IBaseEnum {
IBaseEnum[] getList();
int getIndex();
class Utils{
public IBaseEnum next(IBaseEnum enumItem, boolean isCycling){
int index = enumItem.getIndex();
IBaseEnum[] list = enumItem.getList();
if (index + 1 < list.length) {
return list[index + 1];
} else if(isCycling)
return list[0];
else
return null;
}
public IBaseEnum previous(IBaseEnum enumItem, boolean isCycling) {
int index = enumItem.getIndex();
IBaseEnum[] list = enumItem.getList();
IBaseEnum previous;
if (index - 1 >= 0) {
previous = list[index - 1];
}
else {
if (isCycling)
previous = list[list.length - 1];
else
previous = null;
}
return previous;
}
}
}
这就是我们使用它的方式
enum ColorEnum implements IBaseEnum {
RED,
YELLOW,
BLUE;
@Override
public IBaseEnum[] getList() {
return values();
}
@Override
public int getIndex() {
return ordinal();
}
public ColorEnum getNext(){
return (ColorEnum) new Utils().next(this,false);
}
public ColorEnum getPrevious(){
return (ColorEnum) new Utils().previous(this,false);
}
}
你也可以在界面上添加getNext / getPrevious