Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding downcasting when calling interface methods

Tags:

java

Ok, Im having a stupid moment.

I want to be able to do something like this

class Example {
    public State currentState;
}

interface State{}

interface StateCallbacks
{
    public void onState(IdleState state);
    public void onState(ContactingState state);
    public void onState(SuccessState state);
    public void onState(FailedState state);
}

and be able to call onState(exampleInstance.currentState)) and have the right method called.

Now Im aware why this cant be done, as there is no garentee that there would exist an onState method fir all infinite possible subclasses of State.

My question is whats a good way to achieve something like this without the instanceOf operator. For example i could just include an onState(State) method, but then the implementor would end up using instanceOf.

The idea is that a View object would implement the callback interface and put view-manipulation logic in depending on the state passed. Each state may have complex meta-data associated.

AFAIK it can be done with event buses that support event and/or subscriber inheritance, but only by the nature of how these things work and the EventBus doesnt care if there is no event handling method defined to handle a particular event, unlike our friend the compiler.

I know its a simple problem, but well the problem is, I too am simple.

Many thanks for any suggestions :)

like image 872
Dori Avatar asked Feb 12 '23 21:02

Dori


1 Answers

This is typically solved by using the visitor pattern.

You implement it as follows:

interface State {
    void accept(StateCallbacks visitor);
}

and then in all State.accept implementations you do visitor.onState(this), so for instance IdleState would look as follows:

public class IdleState implements State {
    ...
    void accept(StateCallbacks visitor) {
        visitor.onState(this);
    }
}

(Note that what you call StateCallbacks would in the visitor pattern typically be called a StateVisitor.)

You can then invoke the correct method with, say,

exampleInstance.currentState.accept(new StatePrinter());

if you want to do some custom printing of the current state.

like image 127
aioobe Avatar answered Feb 14 '23 10:02

aioobe