[英]Swift generic protocol issue?
我正在測試一個簡單的 Swift Redux 實現。 有人可以解釋為什么調用store.dispatch(.test)
會導致:
Could not cast value of type '(Test.AppAction) -> ()' to '(Test.Action) -> ()'.
為什么不能將 AppAction 轉換為 Action?,盡管 AppAction 實現了 Action 協議。
中間件接受(S, Action, (Action) -> Void)
,我將它dispatch(_ action: A)
作為第三個參數傳遞。 這是一種((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)
感謝@martin-r 提供線索。 在閱讀@rob-napier 答案后:“但是 function 參數以相反的順序工作。(字符串)-> Void 是您發布的鏈接中的(任何)-> Void 的超類型”,我將代碼重寫為下面的片段。 它可能會節省某人處理相同問題的時間。
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.