Java 中的枚举基类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17820671/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-01 15:07:34  来源:igfitidea点击:

Enum Base Classes in Java

javaenumssubclass

提问by B-Fir3

What is the best way to use this as a base class for an Enum like class. I would like to be able to create different concrete types without having to re-code the getter methods.

将它用作类 Enum 的基类的最佳方法是什么。我希望能够创建不同的具体类型而不必重新编码 getter 方法。

public enum Tool extends Item
{
    Pickaxe("Pickaxe", 101),
    Saw("Saw", 201);
}

And Tool.getNames() would return a list of all the Item names in the Tool class.

Tool.getNames() 将返回 Tool 类中所有项目名称的列表。

public enum Item
{
    Default("Name", 0);

    private final int id;
    private final String name;

    Item(String name, int id)
    {
        this.id = id;
        this.name = name;
    }

    public int getId()
    {
        return this.id;
    }

    public int[] getIds()
    {
        Item[] items = Item.values();
        int[] ids = new int[items.length];
        for (int i = 0; i < items.length; i++)
        {
            ids[i] = items[i].getId();
        }
        return ids;
    }

    public String getName()
    {
        return this.name;
    }

    public String[] getNames()
    {
        Item[] items = Item.values();
        String[] names = new String[items.length];
        for (int i = 0; i < items.length; i++)
        {
            names[i] = items[i].getName();
        }
        return names;
    }
}

I know it isn't possible like this, but how could I approach this situation? I'd like to be able to access the members of each class just like you would an enum: Tool.Pickaxe.

我知道这是不可能的,但我怎么能处理这种情况呢?我希望能够像访问枚举一样访问每个类的成员:Tool.Pickaxe。

回答by skiwi

You will have to implement this yourself, you cannot extend already implemented behaviour. You can however force yourself, or anyone else, to implement various methods:

您必须自己实现这一点,您不能扩展已经实现的行为。但是,您可以强迫自己或其他任何人实施各种方法:

public interface Item {
    public int getId();
    public String getName();
}


public enum Tool implements Item {
    Pickaxe("Pickaxe", 101),
    Saw("Saw", 201);

    private final int id;
    private final String name;

    public Item(final String name, final int id) {
        this.id = id;
        this.name = name;
    }

    @Override
    public int getId() {
        return id;
    }

    @Override
    public String getName() {
        return name;
    }
}

That is part one, now you do not want to access getIds()and getNames()via an enum 'instance' itself, but you want to access them via the class as a static function.

这是第一部分,现在您不想通过枚举“实例”本身访问getIds()getNames()访问它们,但您想通过类作为静态函数访问它们。

I hope this helps you enough already, but it is far from complete and with generics there might even be ways to do it more simpler, but do understand that enums cannot extend anything.

我希望这已经对你有足够的帮助,但它远非完整,并且使用泛型甚至可能有更简单的方法,但要明白枚举不能扩展任何东西。

回答by OldCurmudgeon

You can go part-way.

你可以半途而废。

public class MyItem extends Item<MyItem.Items> {
  public MyItem () {
    // Tell my parent class about my enum.
    super(EnumSet.allOf(Items.class));
  }
  public enum Items implements Item.Items {
    Pickaxe("Pickaxe", 101),
    Saw("Saw", 201);
    private final int id;
    private final String name;

    // You have to do these.
    Items(String name, int id) {
      this.id = id;
      this.name = name;
    }

    @Override
    public int getId() {
      return this.id;
    }

    @Override
    public String getName() {
      return this.name;
    }

  }
}

// The parent class that does the common work.
public class Item<I extends Enum<I> & Item.Items> {
  // Keep track of the items.
  private final Set<I> items;

  // Pas a set of the items in the constructor.
  public Item(Set<I> items) {
    this.items = items;
  }

  // The interface.
  public interface Items {
    public int getId();

    public String getName();

  }

  // Ready-made functionality.
  public List<Integer> getIds() {
    List<Integer> ids = new ArrayList<>();
    for (I i : items) {
      ids.add(i.getId());
    }
    return ids;
  }

  public List<String> getNames() {
    List<String> names = new ArrayList<>();
    for (I i : items) {
      names.add(i.getName());
    }
    return names;
  }

}

Here you still have to have your enum constructor store the fields but you only need to implement an interface. The parent class can then do all of the work on a Set it is given at construct time.

在这里,您仍然需要让您的枚举构造函数存储字段,但您只需要实现一个接口。然后,父类可以在构造时给定的 Set 上完成所有工作。

You can certainly use this technique to move a lot of the code out int a parent class but sadly not all.

您当然可以使用这种技术将大量代码移出父类,但遗憾的是不是全部。