0

I am not too familiar with enum classes in java. And was wondering if this is an appropriate way to do the following.. (or if there is a better way of doing this)

Essentially what I am trying to do is I have a list of Employees and I'd like to associate with it specific subclasses of parent classes.

public enum Employees {
    BOB (new Level2Salary(salaryPlan), new SystemsDept()) 
    MARY (new Level3Salary(salaryPlan), new SoftwareDept()),
    SUSAN (new Level2Salary(salaryPlan), new SystemsDept()),
    PETER (new BaseSalary(salaryPlan), new TestDept());

    private Salary salary;
    private Dept dept;

    Employees(Salary salary, Dept dept){
        this.salary = salary;
        this.dept = dept;
    }

    public Salary getSalary() {
        return salary;
    }

    public Salary getDept() {
        return dept;
    }
}

public class Level2Salary extends Salary {

    private SalaryPlan salaryPlan;

    public Level2Salary(SalaryPlan salaryPlan) {
        this.salaryPLan = salaryPlan;
    }
}

public class SystemsDept extends Dept {
    public SystemsDept(){}
}

}

I want to be able to do this so when I call Employees.BOB.getSalary() it will return the appropriate instantiated subclass that is associated with this enum value. (i.e. Level2Salary subclass)

If anyone has better suggestions of this besides using enums, feel free to suggest. Thanks

1
  • enums are meant more for states or flags, like RED, GREEN, BLUE. If you want a List of employees, see e.g. List<E> interface and implementations. With polymorphism and subclassing, you can do List<Employee> where Employee is class with members SalaryPlan and Dept. If you'd like I'll write a more detailed answer when i get time Commented May 31, 2016 at 14:27

1 Answer 1

1

That cannot be done with an enum. However, you can make a non-enum class which acts just like an enum: Create a class which only has private constructors, but which has public static final fields whose types are the class itself. Many classes introduced before Java 5 are examples of this, such as:

The newer StandardSocketOptions not only follows the above pattern, but also uses generics to do exactly what you want: It allows the NetworkChannel.getOption method to return a different subtype for each constant.

In your case, you would replace your enum type with a class designed like StandardSocketOptions:

public class Employees<S extends Salary, D extends Dept> {

    public static final Employees<Level2Salary, SystemsDept> BOB =
        new Employees<>(new Level2Salary(salaryPlan), new SystemsDept());

    public static final Employees<Level3Salary, SoftwareDept> MARY =
        new Employees<>(new Level3Salary(salaryPlan), new SoftwareDept());

    public static final Employees<Level2Salary, SystemsDept> SUSAN =
        new Employees<>(new Level2Salary(salaryPlan), new SystemsDept());

    public static final Employees<BaseSalary, TestDept> PETER =
        new Employees<>(new BaseSalary(salaryPlan), new TestDept());

    private final S salary;
    private final D dept;

    private Employees(S salary, D dept){
        this.salary = salary;
        this.dept = dept;
    }

    public S getSalary() {
        return salary;
    }

    public D getDept() {
        return dept;
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

I like this solution..but how do I tell the subclass what "salaryPlan" is when instantiating?
You'd need some kind of builder method, which obviously prevents you fro hardcoding the employees in as final fields.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.