Are enums less maintainable than public static final constants?

3.5k views Asked by At

I was recently discussing enums vs public static final constants with a friend. I told him that public static final constants are more maintainable than enums, sometimes faster (android developer docs confirm this), and more convenient as well. I also said that you lose functionality when using enums as well:

  1. You cannot extend an enum.
  2. You cannot instantiate an enum.

He then said you shouldn't be using an enum if you need to instantiate or extend an enum. I then replied that's why we should just use constants because it is more maintainable; What if mid project we need to instantiate an enum or extend it? Then we would have to change everything.

An example demonstrating enums vs constants I made to illustrate my point:

public enum WeekDay {
/*
 * We will start at 1 for demonstration
 */
SUNDAY("Sunday", 1), MONDAY("Monday", 2), TUESDAY("Tuesday", 3), WEDNESDAY(
        "Wednesday", 4), THURSDAY("Thursday", 5), FRIDAY("Friday", 6), SATURDAY(
        "Saturday", 7);
/*
 * Notice we cannot do this...This is where enums fail.
 */
// LUNES("lunes",1), MARTES("martes",2);

private String dayName;
private int dayIndex;

private WeekDay(String dayName, int dayIndex) {
    this.dayName = dayName;
    this.dayIndex = dayIndex;
}

public String getDayName() {
    return dayName;
}

public void setDayName(String dayName) {
    this.dayName = dayName;
}

public int getDayIndex() {
    return dayIndex;
}

public void setDayIndex(int dayIndex) {
    this.dayIndex = dayIndex;
}

@Override
public String toString() {
    return this.dayName + ":  " + this.dayIndex;
}

}

What if we need Spanish week days as well? The enum falls short because you cannot extend it (you would have to do some copy and paste action).

Contrast the enum with this:

public class WeekDayClass {

    private int dayIndex;
    private String dayName;

    public WeekDayClass(int dayIndex, String dayName) {
        super();
        this.dayIndex = dayIndex;
        this.dayName = dayName;
    }

    public int getDayIndex() {
        return dayIndex;
    }

    public void setDayIndex(int dayIndex) {
        this.dayIndex = dayIndex;
    }

    public String getDayName() {
        return dayName;
    }

    public void setDayName(String dayName) {
        this.dayName = dayName;
    }

    @Override
    public String toString() {
        return this.dayName + ":  " + this.dayIndex;
    }

    abstract static class Constants {

    }


    public static void main(String[] args) {
        WeekDayClass init = new WeekDayClass(10, "I can init new days here");

    }
}

And then I can extend it and make AmericanWeekDays:

public class AmericanWeekDay extends WeekDayClass {
    public AmericanWeekDay(int dayIndex, String dayName) {
        super(dayIndex, dayName);
    }

    static class AmericanConstants extends Constants {
        public static final WeekDayClass SUNDAY = new WeekDayClass(1, "Sunday");
        public static final WeekDayClass MONDAY = new WeekDayClass(2, "Monday");
        /*
         * And so on...
         */
    }

}

Or Spanish Week Days:

 public class SpanishWeekDays extends WeekDayClass {

    public SpanishWeekDays(int dayIndex, String dayName) {
        super(dayIndex, dayName);
    }

    static class SpanishConstants extends Constants {
        public static final SpanishWeekDays LUNES = new SpanishWeekDays(2, "lunes");
        /*
         * And so on...
         */
    }

}

Also to go even further:

public class WeekDayClass {

    private int dayIndex;
    private String dayName;

    public WeekDayClass(int dayIndex, String dayName) {
        super();
        this.dayIndex = dayIndex;
        this.dayName = dayName;
    }

    public int getDayIndex() {
        return dayIndex;
    }

    public void setDayIndex(int dayIndex) {
        this.dayIndex = dayIndex;
    }

    public String getDayName() {
        return dayName;
    }

    public void setDayName(String dayName) {
        this.dayName = dayName;
    }

    @Override
    public String toString() {
        return this.dayName + ":  " + this.dayIndex;
    }

    static class AmericanConstants {
        /*
         * Insert Constants Here
         */

    }

    static class SpanishConstants {
        /*
         * Insert Constants Here
         */
    }

}

I understand with an enum you could perhaps make a workaround using data structures (Lists) so you accommodate this shortcoming but why bother? With using public static constants I gain inheritance from the base class, cleaner code, possibly shorter code, and easier maintainability.

I also read that you can use enum's to better design "input parameters" but you could also do the same with the public static final constants as shown above.

Enums have the advantage of being able to be used in switch statements and have the inherited enum methods like values(). These methods can also be replicated if needed in "public static final constant" classes. Aside from the switch I don't see any enum advantages.

In conclusion, is an enum really better than public static final constants? If so, where did I go wrong? Is their something I am missing?

EDIT: You cannot use generics in enums as well.

3

There are 3 answers

2
Szymon On BEST ANSWER

I think you're taking the usage of enums way to far and then come to a conclusion that they are not useful.

Enums are simply telling you that there's a limited and predefined number of options to choose from. Nothing more than that. For example, when you see a parameter that is an enum (let's say State) and it has 3 values (Pending, InProgress, Closed), you know that a state of some object can have one of those and only one of those values.

Enums provide an easy way of validating that a proper value is used as you cannot easily select a value that is not proper when coding. They are also a way of documenting as you can easily see what options are available.

0
drew_w On

Enumerations wouldn't exist if they weren't useful - the same can be said of constants. Just like a screwdriver can remove a screw while a hammer can remove a nail - different tools in your programmer "toolbox" can be used for unique and important purposes. I suggest reading more about enumerations and constants and I think you will find why they exist and when to use them.

5
Alexis King On

Enums get you a lot more than you seem to give them credit for, and while sometimes constants are required, this case is probably a win for enums.

First of all, there is no real difference between an "English weekday" and a "Spanish weekday", they represent the same values. Therefore, the best solution would be to do the conversion to string independently of what the values actually are through some kind of localization method. The values don't change with the language, their representation does.

This is entirely doable quickly and easily with enums. Just write it like this (a little pseudocode-y):

public enum Weekday {
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    ...;

    public String toLocalizedString(Language l) {
        // interact with localization files
    }
}

You are conflating the ideas of external representation and internal representation. Your data should be as homogenous as possible because there is only ever going to be one Monday. It might be called different things, but it's still the same value.

Enums also get you a lot of niceness for free, though, which makes your code much clearer and more maintainable in the long run. Type checking, == comparison, and usability in switch are a few, with no boilerplate to speak of.