我有一个类, StateMachine ,这是通用的,允许将不同的状态集合实现为例如枚举。我想使用 StateMachineDelegate 协议通知代理机构状态机进入新的状态。
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) ... } }我需要以某种方式关联 StateMachineDelegate.S == S 在 StateMachine 类,但我不知道如何做到这一点,或者如果可能的话。我试过:
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? ... }但是我试图重做协议正确声明通用类型 StateMachine 。而在创建一个 StateMachine 时,就不得不先声明该委托的类型。
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.
推荐答案看看这个解决方法是否符合您的需求,它使用 @autoclosure 来摆脱递归泛型定义的问题: / p>
See if this workaround is ok for your needs, it uses @autoclosure to get rid of a problem with recursive generic definitions:
class StateMachine<S: Printable, D: StateMachineDelegate where S == D.StateType> { var currentState: S { didSet { // The observer if let delegate = self.delegate { delegate.stateMachine(self, didEnterState: self.currentState) } } } var delegate: D? init(initialState: S) { self.currentState = initialState } } protocol StateMachineDelegate: class { typealias StateType: Printable // Workaround with autoclosure func stateMachine(machine: @autoclosure() -> StateMachine<StateType, Self>, didEnterState newState: StateType) } final class ADelegate: StateMachineDelegate { typealias StateType = Int func stateMachine(machine: @autoclosure () -> StateMachine<StateType, ADelegate>, didEnterState newState: StateType) { // Need to _unbox_ the sander from the closure let sender = machine() println(newState) println("State from sender: \(sender.currentState)") } } let stateMachine = StateMachine<Int, ADelegate>(initialState: 24) stateMachine.delegate = ADelegate() stateMachine.currentState = 50顺便说一下,如果你得到砂光机,可能你不需要得到 newState 。 我使用可打印代替 Hashable 作为示例。
By the way, consider that if you get the sander, probably you don't need to get the newState passed. I used Printable in place of Hashable for the example.
更多推荐
用于泛型类的Swift委托协议
发布评论