1

I have an Enum class with two variables: int id and boolean collidable.
Is there a way to make a constructor that only receives the first variable and correctly fills the second one? Note that the first class variable is the id and it's different for every type value of the Enum.

public enum TileID {
    Grass(1,false),
    GrassTall(2,false),
    GrassFlower1(3,false),
    GrassFlower2(4,false),
    Water(5,false),

    GrassTwig(6,true),
    GrassRock(7,true);


    private final int id;
    private final boolean collidable;

    TileID(int id, boolean collidable) {
        this.id = id;
        this.collidable = collidable;
    }


    public int getId() {
        return id;
    }

    public boolean isCollidable() {
        return collidable;
    }
}


Edit:

I wanted to know if there is a way to access directly the value corresponding to a given id, but I guess there isn't. I found this method on a different post and I think I'll be doing this instead.

public static TileID valueOf(int id) {
        return Arrays.stream(values())
                .filter(legNo -> legNo.id == id)
                .findFirst().orElse(null);
    }


Thanks to everyone that helped.

  • sure. Just add a static counter, which will set the id – Stultuske Jun 20 '20 at 18:05
  • *"Is there a way to make a constructor that only receives the first variable and correctly fills the second one"* - yes, if there is a way to deduce the second value from the first one. If that is the case what is the point of having that as a variable / field anyway, why not create a getter for it that dynamically calculates the number. – luk2302 Jun 20 '20 at 18:06
  • 2
    By the way, you should follow the Java Naming Conventions: enum constants are always written in UPPER_SNAKE_CASE. For example, `GrassTwig` should be `GRASS_TWIG`. – MC Emperor Jun 20 '20 at 18:17

2 Answers2

7

You can call one constructor form another.

Take a look at: How do I call one constructor from another in Java?

Grass(1),
GrassTall(2),
GrassFlower1(3),
GrassFlower2(4),
Water(5),

GrassTwig(6, true),
GrassRock(7, true);

TileID(int id) {
    this(id, false); // false = default value of 'collidable'
}

TileID(int id, boolean collidable) {
    this.id = id;
    this.collidable = collidable;
}

Moreover, you don't have to specify ids everytime. You can:

  • Use a static int that you increment
  • Use the Enum#ordinal() that will return what 'position' a value is in the enum

ABOUT YOUR EDIT:

There is a quicker method if you use the Enum#ordinal() to quickly retreive a corresponding enum. By doing:

public static TileID fromId(int id) {
    return TileID.values()[id];
}

But be aware that you might want to protect this function against negative or too large values.

Enzo Caceres
  • 519
  • 3
  • 15
3

Sure, you can always set the collidable field according to the id using if or switch, as long as there aren't any constants with the same id field but different values for the collidable field.

Just do

TileID(int id) {
    this.id = id;
    this.collidable = id > 5; //or some other condition
}

And then omit the second argument in your constants (Grass(1), GrassTall(2), ...;).

user
  • 7,435
  • 3
  • 14
  • 44