Java 如何启用枚举继承
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35650045/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to enable enum inheritance
提问by Kiran A B
I'm writing a library, which has a predefined set of values for an enum. Let say, my enum looks as below.
我正在编写一个库,它具有一组预定义的枚举值。比方说,我的枚举如下所示。
public enum EnumClass {
FIRST("first"),
SECOND("second"),
THIRD("third");
private String httpMethodType;
}
Now the client, who is using this library may need to add few more values. Let say, the client needs to add CUSTOM_FIRST
and CUSTOM_SECOND
. This is not overwriting any existing values, but makes the enum having 5 values.
现在,使用此库的客户端可能需要添加更多值。比方说,客户端需要添加CUSTOM_FIRST
和CUSTOM_SECOND
。这不会覆盖任何现有值,而是使枚举具有 5 个值。
After this, I should be able to use something like <? extends EnumClass>
to have 5 constant possibilities.
在此之后,我应该能够使用类似<? extends EnumClass>
有 5 种恒定可能性的东西。
What would be the best approach to achieve this?
实现这一目标的最佳方法是什么?
采纳答案by Mena
You cannot have an enum
extend another enum
, and you cannot "add" values to an existing enum
through inheritance.
您不能enum
扩展另一个enum
,也enum
不能通过继承向现有的“添加”值。
However, enum
s can implement interface
s.
但是,enum
s 可以实现interface
s。
What I would do is have the original enum
implement a marker interface
(i.e. no method declarations), then your client could create their own enum
implementing the same interface
.
我要做的是让原始enum
实现一个标记interface
(即没有方法声明),然后您的客户可以创建自己的enum
实现相同的interface
.
Then your enum
values would be referred to by their common interface
.
然后您的enum
值将被它们的 common 引用interface
。
In order to strenghten the requirements, you could have your interface declare relevant methods, e.g. in your case, something in the lines of public String getHTTPMethodType();
.
为了加强要求,您可以让您的接口声明相关方法,例如在您的情况下,在public String getHTTPMethodType();
.
That would force implementing enum
s to provide an implementation for that method.
这将强制实现enum
s 为该方法提供实现。
This setting coupled with adequate API documentation should help adding functionality in a relatively controlled way.
此设置加上足够的 API 文档应该有助于以相对可控的方式添加功能。
Self-contained example(don't mind the lazy names here)
自包含示例(不要介意这里的懒惰名称)
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;
}
}
}
Output
输出
first
POST
回答by wero
Enums are not extensible. To solve your problem simply
枚举不可扩展。简单解决您的问题
- turn the enum in a class
- create constants for the predefined types
- if you want a replacement for
Enum.valueOf
: track all instances of the class in a static map
- 将枚举转换为类
- 为预定义类型创建常量
- 如果您想要替换
Enum.valueOf
:在静态地图中跟踪类的所有实例
For example:
例如:
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");
...
}
回答by Annie
We Fixed enum inheritance issue this way, hope it helps
我们通过这种方式修复了枚举继承问题,希望它有所帮助
Our App has few classes and each has few child views(nested views), in order to be able to navigate between childViews and save the currentChildview we saved them as enum inside each Class. but we had to copy paste, some common functionality like next, previous and etc inside each enum. To avoid that we needed a BaseEnum, we used interface as our base enum:
我们的应用程序很少有类,每个类都有很少的子视图(嵌套视图),为了能够在 childViews 之间导航并保存 currentChildview,我们将它们保存为每个类中的枚举。但是我们必须在每个枚举中复制粘贴,一些常见的功能,如下一个、上一个等。为了避免我们需要一个 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;
}
}
}
and this is how we used it
这就是我们如何使用它
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);
}
}
you could add getNext /getPrevious to the interface too
您也可以将 getNext /getPrevious 添加到界面
回答by Fertonder Brate
Think about Enum like a final class with static final instances of itself. Of course you cannot extend final class, but you can use non-final class with static final instances in your library. You can see example of this kind of definition in JDK. Class java.util.logging.Level can be extended with class containing additional set of logging levels.
将 Enum 视为具有自身静态最终实例的最终类。当然你不能扩展 final 类,但是你可以在你的库中使用带有静态 final 实例的非 final 类。您可以在 JDK 中看到此类定义的示例。类 java.util.logging.Level 可以使用包含附加日志级别集的类进行扩展。
If you accept this way of implementation, your library code example can be like:
如果您接受这种实现方式,您的库代码示例可以是这样的:
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;
}
}
Client application can extend list of static members with inheritance:
客户端应用程序可以通过继承扩展静态成员列表:
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);
}
}
I think that this solution is close to what you have asked, because all static instances are visible from client class, and all of them will satisfy your generic wildcard.
我认为这个解决方案与您所要求的很接近,因为所有静态实例都可以从客户端类中看到,并且它们都将满足您的通用通配符。