Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum Base Classes in Java

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.

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.

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.

like image 472
B-Fir3 Avatar asked Jul 23 '13 20:07

B-Fir3


People also ask

What is an enum class in Java?

An enum is a special "class" that represents a group of constants (unchangeable variables, like final variables). To create an enum , use the enum keyword (instead of class or interface), and separate the constants with a comma.

Is enum type or class in Java?

In Java, enum types are considered to be a special type of class. It was introduced with the release of Java 5. An enum class can include methods and fields just like regular classes. When we create an enum class, the compiler will create instances (objects) of each enum constants.

Does enum contain class?

Yes, we can define an enumeration inside a class.

What type is enum class?

An enum type is a special data type that enables for a variable to be a set of predefined constants. The variable must be equal to one of the values that have been predefined for it.


2 Answers

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.

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.

like image 114
skiwi Avatar answered Sep 21 '22 01:09

skiwi


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.

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

like image 37
OldCurmudgeon Avatar answered Sep 21 '22 01:09

OldCurmudgeon