0

I have a base class with two derived classes which all seem to use the same enum. I want to use the enum at the base class, but change the assigned value depending on the instance of the derived class used. How do I do this?

The Base class:

public class Base {
    private MyEnum data = MyEnum.Z;
    public Base() {

    }
    public void baseMethod() {
        System.out.println("base data:? "+MyEnum.X);
        data = MyEnum.Y;
        data.showVal();
        System.out.println("base value:? "+data);
    }
    //enum yet to be added
        protected enum MyEnum {
            X(0,2),
            Y(1,3),
            Z(4,5);
            private int a,b;
            MyEnum(int x, int y) {
                a=x;
                b=y;
            }
            public void showVal() {
                System.out.println("a="+a+",b="+b);
            }
        }
}

The two derived classes:

public class A extends Base {
    private MyEnum data = MyEnum.Z;
    public A () {

    }
    public void firstMethod() {
        System.out.println("A's DATA: "+MyEnum.X);
        data = MyEnum.Y;
        data.showVal();
        System.out.println("A's value: "+data);
        baseMethod();
    }
        protected enum MyEnum {
           //values are different
            X(10,11),
            Y(12,13),
            Z(14,15);
            private int a,b;
            MyEnum(int x, int y) {
                a=x;
                b=y;
            }
            public void showVal() {
                System.out.println("a="+a+",b="+b);
            }
        }
}

public class B extends Base {
    private MyEnum data = MyEnum.Z;
    public B() {

    }
    public void secondMethod() {
        System.out.println("B'S DATA: "+MyEnum.X);
        data = MyEnum.Y;
        data.showVal();
        System.out.println("B's value: "+data);
        baseMethod();
    }
        protected enum MyEnum {
            //values are different
            X(20,21),
            Y(22,23),
            Z(24,25);
            private int a,b;
            MyEnum(int x, int y) {
                a=x;
                b=y;
            }
            public void showVal() {
                System.out.println("a="+a+",b="+b);
            }
        }
}

Please help.

user2281204
  • 81
  • 1
  • 3
  • 13
  • This code looks wrong for many reasons, including the protected Enum override, code duplication, and strange class extends. Why don't you use an interface instead ? Is there a reason you use Enums at all ? – Guillaume F. Nov 25 '15 at 17:45
  • 1
    In c++ this would be so easy using templates... So, if I understand you correctly, you want the values of X, Y and Z to be the same for every instance of a specific subclass but different for different subclasses. Well, enums aren't the right tool for the job. This sounds more like you need static fields in your classes – Jupiter Nov 25 '15 at 17:45
  • @GuillaumeF. this is the existing code, and I want to optimize it by removing the duplications, but the main problem is the enum. Also, I need the entire enum value X rather than the individual data. Is there any way to optimize it? – user2281204 Nov 25 '15 at 17:50

2 Answers2

1

Enums are basically final classes that you can't extend. You can implement an interface in an enum, but you cannot extend an enum to change one of its methods or the concrete values of the enum (the pair of integers you're referring to).

If you want to keep using enums, a solution to consider is to have a single MyEnum enum with X, Y, Z and to add a showVal(MyEnum value) method in the objects Base, A and B. The showVal method would simply associate the correct pair of integers for all your enum values (X, Y and Z).

Here is the logic for this approach:

MyEnum.java

public enum MyEnum{
    X,Y,Z
}

Main.java

public class Main{

     public static void main(String []args){
        MyEnum value = MyEnum.X;

        System.out.println("With Base:");
        Base base = new Base();
        System.out.println(base.showVal(value));//prints "a=0,b=2"

        System.out.println("With A:");
        A a = new A();
        System.out.println(a.showVal(value));   //prints "a=10,b=11"

        System.out.println("With B:");
        B b = new B();
        System.out.println(b.showVal(value));   //prints "a=20,b=21"

     }
}

Base.java

public class Base{

    public Base(){
        //Do something...
    }

    public String showVal(MyEnum value){
        switch(value){
            case MyEnum.X:
                return "a=0,b=2";
            case MyEnum.Y:
                return "a=1,b=3";
            case MyEnum.Z:
                return "a=4,b=5";
        }

    }
}

A.java

public class A extends Base{

    public A(){
        //Do something...
    }

    @Override
    public String showVal(MyEnum value){
        switch(value){
            case MyEnum.X:
                return "a=10,b=11";
            case MyEnum.Y:
                return "a=12,b=13";
            case MyEnum.Z:
                return "a=14,b=15";
        }

    }
}

B.java

public class B extends Base{

    public B(){
        //Do something...
    }

    @Override
    public String showVal(MyEnum value){
        switch(value){
            case MyEnum.X:
                return "a=20,b=21";
            case MyEnum.Y:
                return "a=22,b=23";
            case MyEnum.Z:
                return "a=24,b=25";
        }

    }
}

If you don't mind changing your structure, use an object to store a state representing X, Y or Z. You will be able to extend that parent object and give whatever par of integers you want in the child objects.

Community
  • 1
  • 1
Cydrick Trudel
  • 9,957
  • 8
  • 41
  • 63
0

I do agree with @cydrickt, below there is a possible solution, changing the structure of your MyEnum.

I created a simple interface called IMyEnum which has a method to create a Pair of values:

public interface IMyEnum {
    void showVal();

    Pair getPair();
}

public class Pair {

    private final int a;

    private final int b;

    public Pair(int a, int b) {
        this.a = a;
        this.b = b;
    }

    public int getA() {
        return a;
    }

    public int getB() {
        return b;
    }
}

All MyEnum classes implement the IMyEnum interface and each one of the enum constants override the getPair method, returning the appropriate values for a and b. I also made the data attribute of the Base class to be protected and refers to the IMyEnum type. Here is an example of the Base class after this refactoring:

public class Base {

protected IMyEnum data = MyEnum.Z;

public Base() {

}

public void baseMethod() {
    System.out.println("base data:? " + MyEnum.X);
    data = MyEnum.Y;
    data.showVal();
    System.out.println("base value:? " + data);
}

// enum yet to be added
protected enum MyEnum implements IMyEnum {
    X(0, 2) {
        @Override
        public Pair getPair() {
            return new Pair(X.a, X.b);
        }
    },
    Y(1, 3) {
        @Override
        public Pair getPair() {
            return new Pair(Y.a, Y.b);
        }
    },
    Z(4, 5) {
        @Override
        public Pair getPair() {
            return new Pair(Z.a, Z.b);
        }
    };
    private int a, b;

    MyEnum(int x, int y) {
        a = x;
        b = y;
    }

    @Override
    public void showVal() {
        System.out.println("a=" + a + ",b=" + b);
    }
 }
}

The other two classes A and B are similar to the Base class, its MyEnum class have to implement the IMyEnum interface and each X, Y and Z constants override the getPair method.

Rafael Naufal
  • 411
  • 3
  • 6