Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java same enum with different values

Tags:

java

enums

I use a enum to define several variations which can be added to a product (custom logo, colors, etc.). Each variation has several options (ID, description in two languages, where in the process the changes are made, price, etc.). It has methods to define the variation further (for example which color should be used) or to override certain options. One product can either have zero, one or more variations stored in an ArrayList. Also a certain variation can be applied to one product more than once.

As long as I use a variation only once everything is fine. But in case I use it more than once it appears that all get the same options.

Sample code:

TestClass.java:

import java.util.ArrayList;

public class TestClass {
public static void main(String[] args) {
    ArrayList<TestEnum> enums = new ArrayList<>();
    TestEnum enumVar;

    enumVar = TestEnum.TEST1;
    enums.add(enumVar);
    enumVar = null;

    enumVar = TestEnum.TEST2;
    enums.add(enumVar);
    enumVar = null;

    enumVar = TestEnum.TEST2;
    enumVar.setOp1("new op21");
    enumVar.setOp2("new op22");
    enumVar.setOp3("new op23");
    enums.add(enumVar);
    enumVar = null;

    enums.forEach((element) -> {
        System.out.println("op1: " + element.getOp1() + "; op2: " + element.getOp2() + "; op3: " + element.getOp3());
        /*
        Expecting:
        op1: op11; op2: op12; op3: op13
        op1: op21; op2: op22; op3: op23
        op1: new op21; op2: new op22; op3: new op23

        Output:
        op1: op11; op2: op12; op3: op13
        op1: new op21; op2: new op22; op3: new op23
        op1: new op21; op2: new op22; op3: new op23
        */
    });
}
}

TestEnum.java:

public enum TestEnum {
TEST1("op11", "op12", "op13"),
TEST2("op21", "op22", "op23"),
TEST3("op31", "op32", "op33"),
TEST4("op41", "op42", "op43"),
TEST5("op51", "op52", "op53");

private String op1;
private String op2;
private String op3;

TestEnum(String op1, String op2, String op3) {
    this.op1 = op1;
    this.op2 = op2;
    this.op3 = op3;
}

public void setOp1(String op1) {
    this.op1 = op1;
}

public String getOp1() {
    return this.op1;
}

public void setOp2(String op2) {
    this.op2 = op2;
}

public String getOp2() {
    return this.op2;
}

public void setOp3(String op3) {
    this.op3 = op3;
}

public String getOp3() {
    return this.op3;
}
}

Is it possible to do what I have in mind with an enum?

If yes, what do I do wrong? Maybe there is any possibility to create a copy of an enum in a certain state?

like image 809
trik Avatar asked Nov 24 '15 20:11

trik


2 Answers

No, enums are not a good fit for describing objects which are similar but have different states.

Enum constants are static. You don't have two different instances of TEST1. You have just one. Both of the list entries that refer to TEST2 in your example, refer to the same instance. It's not a copy, it's a second reference.

To have instances that are similar but have slightly different states, you should declare a class, not an enum. You could use an enum to describe the type of variation (e.g. COLOR_VARIATION, CUSTOM_LOGO). You could have two different classes that extend a class called Variation or use it directly - depends if the implementation details are different. But you will be using new Variation(...) or using a static factory method to create a new instance of Variation, and then, each Variation instance can have a different set of values in its fields, even if they are both of the same "variation type".

like image 122
RealSkeptic Avatar answered Nov 05 '22 06:11

RealSkeptic


No, you can't do that with enums. There is always exactly one instance of each enum value. If you change the data on the enum (e.g. with one of your setOpn() methods) it is changed globally, because there is only one.

It's best to make the data on an enum immutable. Then, for the variable options, you can associate an ArrayList with each thing that has options, and assign it one of the enums.

You could do it like this:

public class ThingWithOptionsAndEnum {
    private final TestEnum myBaseOptions;
    private final ArrayList<String> myAdditionalOptions = new ArrayList<>();

    public ThingWithOptionsAndEnum(final TestEnum base, String... options) {
        this.myBaseOptions = base;
        if (options != null) {
            for (String option : options) {
                myAdditionalOptions.add(option);
            }
        }
    }
}
like image 31
Erick G. Hagstrom Avatar answered Nov 05 '22 05:11

Erick G. Hagstrom