Как включить наследование enum
Я пишу библиотеку, которая имеет предопределенный набор значений для перечисления. Скажем, мое перечисление выглядит следующим образом.
public enum EnumClass {
FIRST("first"),
SECOND("second"),
THIRD("third");
private String httpMethodType;
}
Теперь клиенту, который использует эту библиотеку, возможно, потребуется добавить еще несколько значений. Скажем, клиент должен добавить CUSTOM_FIRST
и CUSTOM_SECOND
. Это не перезаписывает любые существующие значения, но делает перечисление, имеющее 5 значений.
После этого я должен использовать что-то вроде <? extends EnumClass>
<? extends EnumClass>
чтобы иметь 5 постоянных возможностей.
Какой был бы лучший подход для достижения этого?
Ответы
Ответ 1
Вы не можете enum
еще одно enum
, и вы не можете "добавить" значения к существующему enum
через наследование.
Однако enum
может реализовать interface
s.
Я бы сделал, чтобы исходный 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
Ответ 2
Перечисления не являются расширяемыми. Чтобы решить вашу проблему просто
- превратить перечисление в класс
- создавать константы для предопределенных типов
- если вы хотите заменить
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");
...
}
Ответ 3
Мы исправили проблему наследования enum таким образом, надеемся, что это поможет
Наше приложение имеет несколько классов, и каждый из них имеет несколько дочерних представлений (вложенные представления), чтобы иметь возможность перемещаться между дочерними элементами и сохранять текущую версию Childview, мы сохранили их как перечисление внутри каждого класса. но мы должны были скопировать пасту, некоторые общие функции, такие как следующий, предыдущий и т.д. внутри каждого перечисления. Чтобы избежать этого, нам понадобился BaseEnum, мы использовали интерфейс в качестве нашего базового перечисления:
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 к интерфейсу