【问题标题】:Swift protocol conformance issue with sub type of protocolSwift 协议与子类型协议的一致性问题
【发布时间】:2020-11-27 19:05:37
【问题描述】:
internal protocol Reducer {
        associatedtype S : BaseState
        associatedtype A : BaseAction
        
        func reduce(state: S, action: A) -> S
    }
    
    internal class ReducerImpl : Reducer {
        func reduce(state: MainState, action: MainAction) -> MainState { //<-- Error because MainAction is a protocol not a concrete one.
            return state
        }
    }
    
    internal class MainState : BaseState {}
    internal protocol MainAction : BaseAction {}
    
    internal protocol BaseState {}
    internal protocol BaseAction {}

如果我将MainAction 从协议更改为类,编译错误就会消失。

我搜索了很多文章以了解此错误但失败了。

我必须在reduce(...) 函数中传递一个具体 参数(例如枚举、类、结构)吗?

我想让ReducerImpl可以采取各种符合MainAction的动作类型。

有没有人可以给我解释一下这个错误以及为什么 Swift 采用这种规则。

【问题讨论】:

  • 这感觉像是一种非常精细的方式来表达一个简单的功能。你能举一个依赖这个协议的调用代码的例子吗?您需要“Base...”协议的事实表明您尝试使用协议重新发明类继承(以及您将其称为“子类型”的事实,这不是考虑需要其他协议的协议的好方法)。从调用代码和您尝试实现的算法开始,协议将随之而来。协议不是抽象类。它是一组带有语义的需求,允许你编写算法。
  • 我越看这个,这个协议唯一可能的(纯粹的,非崩溃的)实现是ReducerImpl。使用action 参数实际上是不可能的。我知道您已经简化了问题的内容,但是当您删除了问题的要点时,就会出现问题。不可能将此协议用于有用的目的,这表明您已删除将提供答案的部分。
  • 您需要什么BaseStateBaseState?我假设 reducer 可以对多种数据类型进行操作,因此将它们都限制在一个通用协议中以便在 reducer 中使用它似乎是不可行的。放弃这两个Base 协议,它们带来的问题比解决的问题多。

标签: swift


【解决方案1】:

associatedtype 必须是具体的,即。 type 而不是 protocol

您可以做的是使用接受MainAction 参数的通用函数创建一个更窄的协议:

internal protocol MainReducer {
    associatedtype State
    func reduce<Action>(state: State, action: Action) -> State where Action: MainAction
}

internal class ReducerImpl: MainReducer {
    func reduce<Action>(state: MainState, action: Action) -> MainState where Action: MainAction {
        return state
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-13
    • 1970-01-01
    相关资源
    最近更新 更多