You cannot use a generic type declared at the method level for a method argument that requires a generic type declared elsewhere

My ultimate goal is to have StateTransitionTablewhere the client can create an entry consisting of mainState, and claims that it can go from this ground state (stored in ArrayList). This application Scriptruns in a loop, and the transition table should be somewhat self-acting.

Please do not recommend me to use listings for this; they do not scale well

Each state must have access to Scriptand instances TransitionTable. The script is to do its duty, and the table should go to the next state using the index. Indexes depend on the order in which transitions are added to the record. The first record created is the first record used.

In the application loop, the state stored in the current record should be available and should be called from it process. Scriptcalls <T extends Script> process(T)by passing the current instance of the script:

//this method is called repeatedly
public void loop() {
    table.process(this);
}

mainState currentEntry process(T, TransitionTable), Script . script Script . , , 1 , .

public interface State<T extends Script> {
    void process(T script, TransitionTable table);
}

TransitionTable:

public class TransitionTable {
    private Map<State<?>, StateNode> entries = new HashMap<>();
    private StateNode currentNode, startNode;

    public <T extends Script> void process(T script) {
        currentNode.mainState.process(script, this); //Compile-time error here
    }

    public StateNode createEntry(State<?> state) {
        StateNode node = new StateNode(state);
        map.put(state, node);

        if(startNode == null)
            startNode = currentNode = node;

        return node;
    }

    public void transitionTo(int index) {
        State<?> nextState = currentNode.states.get(index);
        if(nextState == null)
             nextNode = startNode.mainState;

        currentNode = entries.get(nextNode);
    }

    public static final class StateNode {
        private ArrayList<State<?>> states = new ArrayList<>;
        private State<?> mainState;

        public StateNode(State<?> state) {
            mainState = state;
        }

        public StateNode addTransition(State<?> state) {
            states.add(state); 
            return this;
        }
    }
}

process , script. , . .

, :

( # 4-of?, StateTransitionTable) (T, StateTransitionTable)

: , , State. , .

, . - , . , - , ,

+1
2
interface State<T extends Script> {

}

, T, State. , Script, , .

- TransitionTable, , Script , TransitionTable. , , , <T extends Script> .

, TransitionTable ; . StateNode , :

public class TransitionTable<T extends Script<?>> {
    private Map<T, StateNode> entries = new HashMap<>()
    private StateNode current, start;

    public T getCurrentState() {
        return current.state;
    }

    public StateNode createNode(T state) {
        StateNode entry = new StateNode(state);
        entries.put(state, entry);

        if (startNode == null) {
            startNode = currentNode = entry;
        }
        return entry;
    }

    public class StateNode {
        private ArrayList<T> nodes = new ArrayList<>();
        private T state;

        private StateNode(T state) {
            this.state = state;
        }

        public StateNode addTransition(T state) {
            nodes.add(state);
            return this;
        }
    }
}

, :

State<DemoScript> start = new StartState();
State<DemoScript> walkToA = new WalkToAState();
State<DemoScript> walkToB = new WalkToBState();
State<DemoScript> dance = new DanceState();

TransitionTable<State<DemoScript>> table = new TransitionTable();
table.createNode(start).addTransition(walkToA).addTransition(walkToB);
table.createNode(dance).addTransition(walkToA).addTransition(walkToB);
table.createNode(walkToA).addTransition(dance);
table.createNode(walkToB).addTransition(dance);

public void loop() {
    table.getCurrentState().process(this, table);
}

, ;

+1

- , - , script, , , () . - Class<T> Class.isAssignableFrom.

. , process TransitionTable - :

public <T extends Script> Processor<T> getProcessorForCurrentState() {
    //This cast can't go wrong because we haven't bound T yet
    State<T> current = (State<T>)currentNode.mainState;
    return new Processor<T>(current);
}

public static class Processor<T extends Script> {
    private State<T> state;
    private Processor(State<T> state) {
        this.state = state;
    }

    public void process(T script) {
        //TODO make sure this isn't called twice
        this.state.process(script);
    }
}

. , .

0