Ho una classe, StateMachine
, che è generica per consentire l'implementazione di diversi set di stati come, ad esempio, un enum. Voglio utilizzare un protocollo StateMachineDelegate
per informare un delegato quando la macchina di stato entra in un nuovo stato.Protocollo Swift delegato per classe generica
Ma questo non funziona poiché il protocollo delegato è anche generico con i requisiti del tipo. L'errore mostra dove viene dichiarata la proprietà delegate
.
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)
...
}
}
ho bisogno di associare in qualche modo che StateMachineDelegate.S == S
nella classe StateMachine
, ma non sono sicuro come fare questo, o se è possibile. Ho provato:
class StateMachine<S: StateType, D: StateMachineDelegate where D.S == S> {
...
weak var delegate: D?
...
}
ma poi mi si blocca cercando di rielaborare il protocollo di dichiarare correttamente il tipo generico di StateMachine
. E non sembra giusto dover dichiarare in anticipo il tipo di delegato durante la creazione di uno StateMachine
.
A proposito, dato che la macchina a stati è un buon modello di progettazione per molti problemi, perché limitare lo stato ad essere lavabile? Perdi il potere dell'enumerazione con valori associati (o almeno dovrai conformarli a hashable). Le enumerazioni IMHO con i valori associati sono ottime per le logiche delle macchine a stati. –
Grazie, ma questo non funziona. Penso che il problema sia un po 'più profondo. La mia ipotesi è che il compilatore non possa (per qualsiasi motivo) garantire che i requisiti di tipo 'StateMachineDelegate' saranno soddisfatti, dato che' StateMachine' non promette nulla al riguardo. Se 'StateMachine' includeva un parametro di tipo _generico_ vincolato a' StateMachineDelegate', allora è promettente che verrà sostituito con una classe soddisfacente in fase di esecuzione (ma poi finisco con un parametro dispari di 'StateMachine
' nel protocollo delegato) . Forse diventerà possibile man mano che la lingua si sviluppa. – StuartPer quanto riguarda il vincolo hashable, l'ho fatto perché la macchina di stato memorizza effettivamente stati e transizioni di stato e controlla la loro esistenza per determinare se una modifica dello stato richiesta è valida. La lezione è un po 'più complessa di quella che ho mostrato nella domanda, e diventerà più complessa man mano che sperimenterò ulteriormente! Se le enumerazioni associate sono a portata di mano, non dovrebbe essere un problema conformarle a 'Hashable', come suggerisci tu. – Stuart