Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are enums less maintainable than public static final constants?

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.

like image 567
horvste Avatar asked Dec 13 '13 04:12

horvste


People also ask

Is it better to use enum or constant?

Enums are lists of constants. When you need a predefined list of values which do represent some kind of numeric or textual data, you should use an enum. You should always use enums when a variable (especially a method parameter) can only take one out of a small set of possible values.

Why enums are better than constants Java?

Enums limit you to the required set of inputs whereas even if you use constant strings you still can use other String not part of your logic. This helps you to not make a mistake, to enter something out of the domain, while entering data and also improves the program readability.

Are enums efficient?

Enums are crucial part of every application larger than “Hello World“. We use them everywhere. They are actually very useful: they restrict the input, allow you to compare the values by the reference, provide compile-time checks, and make the code easier to read.


1 Answers

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.

like image 173
Alexis King Avatar answered Sep 28 '22 02:09

Alexis King