简体   繁体   English

Swift 通用协议问题?

[英]Swift generic protocol issue?

I'm testing a simple Swift Redux implementation.我正在测试一个简单的 Swift Redux 实现。 Could somebody explain why calling store.dispatch(.test) causes:有人可以解释为什么调用store.dispatch(.test)会导致:

Could not cast value of type '(Test.AppAction) -> ()' to '(Test.Action) -> ()'.

Why it is not possible to cast AppAction to Action?, although AppAction implements Action protocol.为什么不能将 AppAction 转换为 Action?,尽管 AppAction 实现了 Action 协议。

Middleware accepts (S, Action, (Action) -> Void) , I pass it dispatch(_ action: A) as the 3rd param.中间件接受(S, Action, (Action) -> Void) ,我将它dispatch(_ action: A)作为第三个参数传递。 which is a type of ((Action) -> Void) but it can't accept it.这是一种((Action) -> Void)但它不能接受它。

protocol State {}
protocol Action {}

typealias Reducer<S: State, A: Action> = (S, A) -> S
typealias Dispatcher = (Action) -> Void
typealias Middleware<S: State> = (S, Action, @escaping Dispatcher) -> Void

protocol Store: ObservableObject {
   associatedtype S: State
   associatedtype A: Action

   func dispatch(action: A)
}

final class DefaultStore<S: State, A: Action>: ObservableObject {
   @Published private(set) var state: S

   private let reducer: Reducer<S, A>
   private let middlewares: [Middleware<S>]

   init(initialState: S, reducer: @escaping Reducer<S, A>, middlewares: [Middleware<S>] = []) {
      self.state = initialState
      self.reducer = reducer
      self.middlewares = middlewares
   }

   func dispatch(_ action: A) {
      state = reducer(state, action)

      middlewares.forEach { middleware in
         middleware(state, action, dispatch as! Dispatcher)
      }
   }
}

// START

struct AppState: State { }
enum AppAction: Action { // A test action to have smthg. to call
   case test
}

let appReducer: Reducer<AppState, AppAction> = { s, a in s }
let middleware: Middleware<AppState> = { s, a, dispatch in }

var store = DefaultStore(initialState: AppState(), reducer: appReducer, middlewares: [middleware])
store.dispatch(.test)

Thanks @martin-r for clues.感谢@martin-r 提供线索。 After reading @rob-napier answer: "But function parameters work in the reverse order. (String)->Void is a supertype of (Any)->Void" from the links you posted, I rewrote the code to snippet bellow.在阅读@rob-napier 答案后:“但是 function 参数以相反的顺序工作。(字符串)-> Void 是您发布的链接中的(任何)-> Void 的超类型”,我将代码重写为下面的片段。 It might save someone's time dealing with the same problem.它可能会节省某人处理相同问题的时间。

protocol State {}
protocol Action {}

typealias Reducer<S: State, A: Action> = (S, A) -> S
typealias Dispatcher<A: Action> = (A) -> Void
typealias Middleware<S: State, A: Action> = (S, A, (A) -> Void) -> Void

protocol Store: ObservableObject {
   associatedtype S: State
   associatedtype A: Action

   func dispatch(action: A)
}

final class DefaultStore<S: State, A: Action>: ObservableObject {
   @Published private(set) var state: S

   private let reducer: Reducer<S, A>
   private let middlewares: [Middleware<S, A>]

   init(initialState: S, reducer: @escaping Reducer<S, A>, middlewares: [Middleware<S, A>] = []) {
      self.state = initialState
      self.reducer = reducer
      self.middlewares = middlewares
   }

   func dispatch(_ action: A) {
      state = reducer(state, action)

      middlewares.forEach { middleware in
         middleware(state, action, dispatch)
      }
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM