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()
}