Juergen
Juergen

Reputation: 3743

State machine default event handling

Consider this enum which I want to use as a state machine:

public enum PositionFSM {

  State1 {
    @Override
    PositionFSM processFoo() {
      return State2;
    }
  },
  State2 {
    @Override
    PositionFSM processFoo() {
      return State1;
    }
  };

  abstract PositionFSM processFoo();

  abstract PositionFSM processBar();

  PositionFSM processBar() {
    return this;
  }
}

The goal is to avoid that all states must implement all events for which they do nothing but return the current state.

In this example a call for processBar should be ignored by State1 and State2.

I'm referring to this answer, but the enum given will not compile(Java 1.8). Is there a way for doing it the way I want?

Upvotes: 1

Views: 316

Answers (4)

vlp
vlp

Reputation: 8116

This one does compile:

ublic enum PositionFSM {

  State1 {
    @Override
    PositionFSM processFoo() {
      return State2;
    }
  },
  State2 {
    @Override
    PositionFSM processFoo() {
      return State1;
    }
  };

  abstract PositionFSM processFoo();

  PositionFSM processBar() {
    return this;
  }
}

The processBar() method was declared twice.


EDIT>

An alternative for Java 8 might be to use an interface with default methods, like this:

public interface IPositionFSM {

    default IPositionFSM processFoo() {
        return this;
    }

    default IPositionFSM processBar() {
        return this;
    }
}

public enum PositionFSM implements IPositionFSM {
    State1 {
        @Override
        public IPositionFSM processFoo() {
            return State2;
        }
    },
    State2 {
        @Override
        public IPositionFSM processBar() {
            return State1;
        }
    };
}

Upvotes: 1

Pinkie Swirl
Pinkie Swirl

Reputation: 2415

You need to define the enum variables first, then the method (I don't know why the linked answer does it the other way around, that never worked in java). Plus don't make the method abstract, so you can provide a default implementation:

public enum State
{
    State1
    {
        @Override
        public State process()
        {
            return State2;
        }
    },
    State2,
    State3;

    public State process()
    {
        return this;
    }
}

To test it:

System.out.println(State.State1.process());
System.out.println(State.State2.process());
System.out.println(State.State3.process());

Produces the following output:

State2
State2
State3

Upvotes: 2

makasprzak
makasprzak

Reputation: 5220

This code does not compile because the processBar() is declared twice. Just remove the line

abstract PositionFSM processBar();

and code will compile.

Upvotes: 1

rajuGT
rajuGT

Reputation: 6414

Just comment the line

abstract PositionFSM processBar();

Because anyway you have given the implementation in your enum class.

  PositionFSM processBar() {
    return this;
  }

Then you can access your enum's both method like below

PositionFSM.State1.processFoo(); //valid no syntax error
PositionFSM.State1.processBar();

If needed you can override the processBar method for any constant like shown below

  State2 {
    @Override
    PositionFSM processFoo() {
      return State1;
    }

    @Override
    PositionFSM processBar(){
        return this;
    }
  };

Upvotes: 3

Related Questions