1

I want store on an enum classes, so later I can instantiate this class. But I don't know how I can do that.

This is an example:

public enum STATE {
 MENU(Menu.class, Color bgColor);
 PLAY(Play.class, Color bgColor);
 ...
 public STATE() {...
 }
}

and having a method for change between states. All the classes on STATE inherit from AState, So for example (public class Menu extends AState{...})

Astate currentState;
public void changeState(STATE s){
  if(currentState != null) currentState.dispose();
  currentState = ...some code to instantiate the class and assign to this value
  currentState.init();
}

My idea is have an enum that holds the class for each state, and a few parameters to instantiate this class with different values like his bgColor, but I don't know how do this in Java.

Erick G. Hagstrom
  • 4,873
  • 1
  • 24
  • 38
Jota_sk
  • 169
  • 2
  • 14

4 Answers4

3

I suggest using an abstract factory method in this enum.

public enum State {
    MENU {
        public AState createInstance() { return new Menu();}
    },
    PLAY {
        public AState createInstance() { return new Play();}
    };

    public abstract AState createInstance();
}

So then you can do:

public void changeState(State s){
    if(currentState != null) currentState.dispose();
    currentState = s.createInstance();
}

I omitted the color field, because it's not clear how it should be used. If color is the same for every state, it can be added as an additional private field to the enum. If you use various colors when constructing a new AState instance, it can be passed as an argument to createInstance() method.

If you use Java 8 this enum could be written in a more elegant way:

public enum State {
    MENU(Menu::new),
    PLAY(Play::new);

    Supplier<AState> stateConstructor;

    State(Supplier<AState> constructor) {
        stateConstructor = constructor;
    }

    public AState createInstance() {
        return stateConstructor.get();
    }
}
Dmitry P.
  • 824
  • 5
  • 14
0

You cannot initialize an enum element through its constructor, which is why enum constructors can either be private or package-protected.

Your public constructor above will fail to compile.

In order to assign an enum value to a reference, you can use the following idiom:

STATE currentState = STATE.MENU;
Mena
  • 47,782
  • 11
  • 87
  • 106
0

The answer for your question is here https://stackoverflow.com/a/6094602/1885467

Astate currentState;
public void changeState(STATE s){
    if(currentState != null) currentState.dispose();
    Constructor<?> ctor = s.clazz.getConstructor();
    currentState = (Astate)ctor.newInstance();
    currentState.init();
}

Although I don't know if there is no better approach to solve the general problem that you have in your application.

Community
  • 1
  • 1
MJar
  • 741
  • 9
  • 26
0

Here is sample code.

public enum SomeEnum {

MENU(SomeState.class, "This is menu");

private Class<? extends State> clazz;
private String value;

SomeEnum(final Class<? extends State> clazz, final String value){
    this.clazz = clazz;
    this.value = value;
}


public State getState() throws InstantiationException, IllegalAccessException{
    State newInstance = clazz.newInstance();
    newInstance.setSomeValue(value);
    return newInstance;
}
}

public class SomeState implements State {

private String value;

@Override
public void runState() {
    System.out.println("Running with value : " + value);
}

@Override
public void setSomeValue(String value) {
    this.value = value;

}

}

public interface State {
void runState();
void setSomeValue(String value);
}

public class Test {
public static void main(String[] args) throws InstantiationException, IllegalAccessException {
    SomeEnum.MENU.getState().runState();
}
}
Ekrem
  • 483
  • 2
  • 16