Ich habe eine Klasse, StateMachine
, die generisch ist, um verschiedene Sätze von Zuständen wie zum Beispiel eine enum zu implementieren. Ich möchte ein StateMachineDelegate
Protokoll verwenden, um einen Delegaten zu benachrichtigen, wenn der Zustandsautomat einen neuen Status eingibt.Swift Delegate-Protokoll für generische Klasse
Dies funktioniert jedoch nicht, da das Delegate-Protokoll auch generisch mit Typanforderungen ist. Der Fehler zeigt an, wo die delegate
-Eigenschaft deklariert ist.
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)
...
}
}
Ich brauche irgendwie, dass StateMachineDelegate.S == S
in der StateMachine
Klasse assoziieren, aber ich bin nicht sicher, wie dies zu tun, oder wenn es möglich ist. Ich habe versucht:
class StateMachine<S: StateType, D: StateMachineDelegate where D.S == S> {
...
weak var delegate: D?
...
}
aber dann stecken ich versucht, das Protokoll zu überarbeiten, um richtig die allgemeine Art der StateMachine
zu erklären. Und es scheint nicht richtig zu sein, den Typ des Delegierten bei der Erstellung eines StateMachine
im Voraus zu deklarieren.
Übrigens, angesichts dieser State Machine ist ein gutes Design-Muster für eine Menge Probleme, warum den Zustand zu beschränken, um hashable? Du verlierst die Macht der Enums mit den zugehörigen Werten (oder zumindest musst du sie mit "hashable" anpassen). IMHO-Enums mit zugehörigen Werten eignen sich hervorragend für State-Machine-Logiken. –
Danke, aber das funktioniert nicht. Ich denke, das Problem läuft ein bisschen tiefer. Meine Vermutung ist, dass der Compiler (aus welchen Gründen auch immer) nicht garantieren kann, dass die Anforderungen des 'StateMachineDelegate'-Typs erfüllt werden, da' StateMachine' in dieser Hinsicht keine Versprechungen macht. Wenn 'StateMachine' einen _generic_ type-Parameter enthält, der auf' StateMachineDelegate' beschränkt ist, dann ist es vielversprechend, dass er zur Laufzeit durch eine befriedigende Klasse ersetzt wird (aber dann lande ich im Delegate-Protokoll mit einem ungeraden Parameter von 'StateMachine
'). . Vielleicht wird es möglich werden, wenn sich die Sprache entwickelt. – StuartIn Bezug auf die hashbare Einschränkung habe ich dies getan, weil die Zustandsmaschine tatsächlich Zustände und Zustandsübergänge speichert und auf ihre Existenz prüft, um festzustellen, ob eine angeforderte Zustandsänderung gültig ist. Die Klasse ist ein bisschen komplexer als ich in der Frage gezeigt habe, und wird komplexer, während ich weiter experimentiere! Wenn verknüpfte Aufzählungen nützlich sind, sollte es kein Problem sein, sie an "Hashable" anzupassen, wie Sie es vorschlagen. – Stuart