I have a class, StateMachine
, that is generic to allow for different sets of states to be implemented as, for example, an enum. I want to use a StateMachineDelegate
protocol to notify a delegate when the state machine enters a new state.
But this doesn't work since the delegate protocol is also generic with type requirements. The error shows where the delegate
property is declared.
protocol StateType: Hashable {}
protocol StateMachineDelegate: class {
typealias S: StateType
func stateMachine(stateMachine: StateMachine<S>, didEnterState newState: S)
}
class StateMachine<S: StateType> {
typealias State = S
weak var delegate: StateMachineDelegate?
//~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~
//Protocol 'StateMachineDelegate' can only be used as a generic constraint because it has Self or associated type requirements
var currentState: State {...}
init(initialState: State) {...}
func applyState(toState: State) -> Bool {
...
currentState = toState
delegate?.stateMachine(self, didEnterState: toState)
...
}
}
I need to somehow associate that StateMachineDelegate.S == S
in the StateMachine
class, but I'm not sure how to do this, or if it's possible. I tried:
class StateMachine<S: StateType, D: StateMachineDelegate where D.S == S> {
...
weak var delegate: D?
...
}
but then I get stuck trying to rework the protocol to properly declare the generic type of StateMachine
. And it doesn't seem right to have to declare the type of the delegate up front when creating a StateMachine
.
See if this workaround is ok for your needs, it uses
@autoclosure
to get rid of a problem with recursive generic definitions:By the way, consider that if you get the sander, probably you don't need to get the
newState
passed. I usedPrintable
in place ofHashable
for the example.I think its just a name collision problem ... try this:
You need to declare what the name of the generic type defined in the protocol should be in the class conforming to it.