user3818619
user3818619

Reputation:

Assign each enum instance a growing ID

I'm just starting my first steps with Java, learned all the basics but then found a problem with an enum I need, so forgive me, if the solution to my problem is something very obvious:

So I've got this enum and want to add a unique id to each instance counting from 0 upwards, but without having to add another parameter to each constructor calling (because this can later on lead to errors ofc).

public enum TerrainTile{

 WATER(1), GRASSLAND(1), HILL(2), FORREST(2), BLANK(99);

private final int id;
private final int moveCost;
private boolean hidden = true;

private TerrainTile(int moveCost) {
    this.moveCost = moveCost;
}

And I thought to just add a

static int nextID = 0;

and edit the constructor to

private TerrainTile(int moveCost) {
    this.id = nextID++;
    this.moveCost = moveCost;
}

But I get an error message that it can not refer to a static field inside the initializer.

Is there any workaround?

Upvotes: 2

Views: 94

Answers (2)

user3802811
user3802811

Reputation:

It sounds like you are trying to combine class features into an enum. I'd be particularly wary of non-final, non-static member fields in an enum declaration. The behaviour you want seems to be best served by using a TerrainTile class (possibly a flyweight if you truly want the single-instance-per-type behaviour) and a TerrainTileType (or TerrainTile.Type) enum. Something like this:

public class TerrainTile {
    public enum Type {
        WATER(1), GRASSLAND(1), HILL(2), FORREST(2), BLANK(-1);
        public final int MOVE_COST;
        private TerrainTile(int moveCost) {
            this.MOVE_COST = moveCost;
        }
        public boolean isTraversable() {
            return (MOVE_COST > 0);
        }
    }

    private final Type type;
    private final Image texture;
    ...
    private TerrainTile(Type type) {
        this.type = type;
    }

    private static final Map<Type, TerrainTile> tiles = new EnumMap<>();
    static {
        // instantiate one TerrainTile for each type and store into the tiles Map
        for (Type type: Type.values()) {
            // Eventually, also load tile textures or set Color in this step
            tiles.put(type, new TerrainTile(type));
        }
    }

    public static TerrainTile getTile(Type type) {
        // return the reference to the TerrainTile of this type
        return tiles.get(type);
    }

    ...
}

Upvotes: 0

Jiri Kremser
Jiri Kremser

Reputation: 12837

You can use the ordinal() method for it. It is based on the order in which the members are declared in the source-code and counted from zero. So I guess, exactly what you need.

Just a note: You can get your original enum member from ordinal number by calling .values()[index]

example:

int hillOrdinal = TerrainTile.HILL.ordinal(); // 2
TerrainTile hill = TerrainTile.values()[hillOrdinal];

Upvotes: 5

Related Questions