commandsDict changes
Looking at this:
var commandsDict: [S : [StateCommand<E>]] = [:]
I can see a few problems with storing the StateCommand<E> objects in an array. The array could possibly hold multiple StateCommand<E> objects with the same event.
This shouldn’t be allowed. There should only be a single state to event relationship.
I could use nested dictionaries:
var commandsDict: [S : [E : StateCommand<E>]] = [:]
One alternative is to use a Set to store the StateCommand objects. The set will store an unordered, unique group of StateCommand
var commandsDict: [S : Set<StateCommand<E>] = [:]
We can use generic typealiases for the Set:
typealias StateCommandSet<E> = Set<StateCommand<E>>
var commandsDict: [S : StateCommandSet<E>] = [:]
Objects that will be stored in a Set data structure must adopt the Hashable protocol. The StateCommand<E> class will need to adopt the Hashable protocol.
class StateCommand<E: Hashable> : Hashable {
var event: E!
var hashValue: Int {
return event.hashValue
}
static func ==(lhs: StateCommand, rhs: StateCommand) -> Bool {
return lhs.event == rhs.event
}
}
The hashValue property returns the hash value of the event variable. In order to access the hash value of the event, we need to add a generic constraint to the class declaration to enforce that the generic type E conforms to the Hashable protocol. Now that StateCommand is compatible with the Set structure, we can add commands to the commandsDict object.
insert a command into the set:
var set: StateCommandSet<E> = StateCommandSet()
var command = StateCommand()
set.insert(command)
to retrieve items from a set use the filter() function:
let eventSet = set.filter { $0.event == .filter }
to get the item from the new set, get the first property:
if let command = eventSet.first {
print(command.nextState)
command.action()
}