I want state diagram states to be values of given enum type. In the second step I'd like to use the state diagram as constraint for a property of previously mentioned enum type, e.g. as argument check in the property's setter.
Still not sure I completely understand what you're trying to achieve. Here's some thoughts however, hope they're useful. Apologies if I've missed the point.
The first question is: why do you want the enum values and states to be isomorphic? In the most general sense that's replicating information. And replicated information has a habit of getting out of sync. So it would be useful to understand the motivation.
Notwithstanding, here's a couple of possibilities.
1. UML / Modelling perspective
In the UML world there's no real need to have both a state model and an enum associated with it. UML in general doesn't define how to read the value of an object's current state; however certain profiles (e.g. Executable UML) do. In Executable UML, any class that has a state machine automatically gets a read-only attribute named current_state
. The possible values for current_state
are the names of the states in the state model. So you could view it as the state machine defining an implicit enum.
Note the attribute is read only. That's because the only way to change it is through the state machine, i.e. by sending events to the object. So it also satisfies your second requirement: it's not possible to change the value of the current_state
variable in a way that violates the state machine protocol.
Even if you're not using the Executable UML profile (or similar) it's perfectly valid to state the above as a rule/convention. If necessary you could define your own profile, although that might be overkill - depends on your circumstances.
The key point is the enum isn't necessary in the modelling world.
2. Code Perspective
When Translating the model to code, an enum is a sensible and common way to define the type for the current state variable. Per the modelling scenario, you'd want to make the current_state
attribute read only to the outside world. You then need three other things:
current_state
variable from within the state machine implementation.So in the code world, you prevent invalid sequences of the current_state
variable by making it read only to the outside world. That is, you only have a public read accessor: there's no public write accessor.
Inside the class, you make the write accessor private and ensure the only place it gets called is within the state machine implementation.
Instead of a public write accessor, you provide public methods corresponding to the events that drive the state machine. More detail on implementing state machines below, but here's a trivial example for now:
class Phone {
enum PhoneState {disconnected, connecting, connected, disconnecting};
public PhoneState current_state {get}; //no write accessor
//functions for generating state machine events
public void digit(int number) {..} //press digit key, e.g. while dialing
public void connect() {..} //make connection
public void disconnect() {..} //disconnect
}
Implementing the State Machine
There are 3 common patterns for implementing state machines: 1. State Matrix or Lookup Table 2. Nested Switch 3. State Pattern
There's a good overview of (1) here; (2) & (3) are covered here.
And that's basically it. Not entirely sure I answered your question. If not apologies, perhaps you could be more specific about what you're trying to achieve.
hth.