Объединение перечислений и использование getter для возврата указанного перечисления
Скажем, у меня есть 2 разных набора перечислений: фрукты и овощи.
public static enum Fruits{
APPLE ("Apple"),
PEAR ("Pear");
//constructor
//getName()
...
}
public static enum Vegetables{
CARROT ("Carrot"),
LETTUCE ("Lettuce");
//constructor
//getName()
...
}
Я показываю все это в JComboBox. После того, как кто-то что-то выбирает, я хочу использовать метод getter, чтобы вернуть Enum.
Для одного перечисления я сделал бы что-то вроде:
public static Fruits getEnum(String name) {
for(Fruits fruit: Fruits.values()) {
if(name.equals(fruit.getName())) {
return fruit;
}
}
return null;
}
Любые идеи, каков тип возврата? Я пытался использовать Enum вместо Fruits. Когда я это делаю, у меня нет доступа к методам getName().
Ответы
Ответ 1
Вот еще одна демонстрация того, что вы ищете. Разница между этим и предыдущими решениями заключается в том, что эта модель является более общей и многоразовой. Это фактически выходит за рамки первоначальной проблемы, чтобы показать некоторые другие преимущества этого подхода. Поэтому вы можете просто прокомментировать биты, которые вам не нужны. Я также прикрепляю unit test для демонстрации поведения.
Итак, в основном для поиска имени Apple
или Apple
в одном из этих перечислений просто напишите:
FruitVeg<?> fvg = getEnum("APPLE", Fruits.class, Vegetables.class);
FruitVeg<>
- это интерфейс, который позволяет также использовать внутри Enum, этот интерфейс позволяет делать некоторые очень интересные вещи с перечислениями ниже. Вот лишь некоторые из вещей, которые вы могли бы сделать с этим:
-
Enum.valueOf(fvg.getDeclaringClass(), fvg.name())
: возвращает значение перечисления, например. APPLE
-
fvg.getRaw()
: возвращает значение перечисления, например. APPLE
-
fvg.name()
: возвращает enum String Name, например. APPLE
-
fvg.getFriendlyName()
: например. Apple
-
fvg.getDeclaringClass()
: возвращает Class<Enum<?>>
, например. класс ox.dummy.dummyTest $Fruits
-
fvg.getClass()
: класс ox.dummy.dummyTest $Fruits возвращает Class<?>
-
EnumSet.allOf(fvg.getDeclaringClass()))
: например. [APPLE, PEAR]
Вот код
@Test
public void doSimpleTest() throws Exception {
FruitVeg<?> fvg = getEnum("APPLE", Fruits.class, Vegetables.class);
log.info("{} : {} : {} : {} : {}", fvg.name(), fvg.getFriendlyName(), fvg.getClass(), fvg.getDeclaringClass(), EnumSet.allOf(fvg.getDeclaringClass()));
log.info("get enum: {} ", Enum.valueOf(fvg.getDeclaringClass(), fvg.name()));
}
public interface FruitVeg<T extends Enum<T>> {
String name();
String getFriendlyName();
Class<T> getDeclaringClass();
T getRaw();
}
enum Fruits implements FruitVeg<Fruits> {
APPLE("Apple"),
PEAR("Pear");
Fruits(String friendlyName) {
this.friendlyName = friendlyName;
}
private final String friendlyName;
@Override
public String getFriendlyName() {
return friendlyName;
}
@Override
public Fruits getRaw() {
return this;
}
}
enum Vegetables implements FruitVeg<Vegetables> {
CARROT("Carrot"),
LETTUCE("Lettuce");
Vegetables(String friendlyName) {
this.friendlyName = friendlyName;
}
private final String friendlyName;
@Override
public String getFriendlyName() {
return friendlyName;
}
@Override
public Vegetables getRaw() {
return this;
}
}
public static FruitVeg<?> getEnum(String name, Class<? extends FruitVeg<?>>... fvgClasses) {
for (Class<? extends FruitVeg<?>> fruitVegCLass : Arrays.asList(fvgClasses)) {
for (FruitVeg<?> fvg : fruitVegCLass.getEnumConstants()) {
if (name.equals(fvg.name()) || name.equals(fvg.getFriendlyName())) {
return fvg;
}
}
}
return null;
}
Ответ 2
Вариант 1.
Создайте один метод, который возвращает Enum
public static Enum getEnum(String name) {
Enum selectedEnum = null;
for (Fruits fruit : Fruits.values()) {
if (name.equals(fruit.getName())) {
selectedEnum = fruit;
}
}
for (Vegetables vegetables : Vegetables.values()) {
if (name.equals(vegetables.getName())) {
selectedEnum = vegetables;
}
}
return selectedEnum;
}
и для получения имени перечисления вы можете использовать этот метод
public static String getName(final Enum value) {
String name = null;
if (value instanceof Fruits) {
name = ((Fruits) value).getName();
} else if (value instanceof Vegetables) {
name = ((Vegetables) value).getName();
}
return name;
}
Вариант 2.
Вы можете объединить 2 перечисления как
public static enum FruitsAndVegitables{
APPLE ("Apple" , true),
PEAR ("Pear", true),
CARROT ("Carrot", false),
LETTUCE ("Lettuce", false);
private String name;
private boolean isFurit;
//constructor
//getName()
...
}
Ответ 3
Перечислите сами перечисления как значения. Затем используйте getSelectedItem для извлечения выбранного объекта и выполните тест, чтобы узнать, какой тип объекта есть.
Сделайте возвращаемым типом своего метода Object, а не перечислением определенного типа. Это устранит вашу проблему.
Однако, я думаю, ваш подход неправильный. Если бы я хотел, чтобы фрукты и овощи отображались в списке и разбивались на категории, я бы создал объект, чтобы сделать это, и перечисление, чтобы представить тип такой пищи:
public enum FoodType{FRUIT, VEGETABLE}
public class Food{
FoodType type;
String name;
public Food(FoodType type, String name){
this.type = type;
this.name = name;
}
public String toString(){return this.name;}
}
//and then when you want to use it...
Food lettuce = new Food(FoodType.VEGETABLE, "Lettuce");
Food berry = new Food(FoodType.BERRY, "Berry");
comboBox.add(lettuces);
comboBox.add(berry);
И добавьте только теги Food
в JComboBox. Возвращайте элементы Food
при выборе и проверяйте тип продукта, используя перечисление FoodType
.
Ответ 4
Похоже, что вы ищете возможность применить наследование к enums
, но это невозможно в java, поскольку enums
implicity extend java.lang.Enum
и java не поддерживает множественное наследование.
Тем не менее, я думаю, что использование вложенных перечислений" могло бы решить вашу проблему. Вложенным я подразумеваю реализацию интерфейса для решения проблемы множественного наследования. В ответах в ссылке есть несколько разных подходов, я предполагаю, что одного из них будет достаточно.
Ответ 5
Вы можете использовать Object
вместо явного использования Fruit
или Vegetables
public static Object getEnum(String name)
{
for(Fruits fruit: Fruits.values())
{
if(name.equals(fruit.getName()))
{
return fruit;
}
}
for(Vegetables vege: Vegetables.values())
{
if(name.equals(Vegetables.getName()))
{
return vege;
}
}
return null;
}
Тем не менее, это означает, что вам придется сравнить и применить результат к тому, что вы хотите
Object o = getEnum("Carrot")
if(o instanceof Vegetable)
{
Vegetable v = (Vegetable)o;
v.getName();
}
//.. and again for fruit