Как включить наследование 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 к интерфейсу