我的代码中有一些协议层次结构,我有定义我使用的对象的协议和定义与这些对象一起使用的函数的协议.
对象协议由其他对象协议继承,这些协议为原始协议添加了更多功能,使用它们的功能也是如此.问题是我找不到专门化函数的方法来只接受继承的参数.
这里有一些代码来澄清我正在尝试做的事情:
protocol A { var foo: String { get set } } protocol B: A { var bar: String { get set } } struct Test: B { var foo: String = "foo" var bar: String = "bar" } protocol UseAProtocol { static func use<T: A>(_ obj: T) } protocol UseBProtocol: UseAProtocol { } extension UseBProtocol { //If I change the requirement to <T: B> this won't conform to `UseAProtocol`. static func use<T: A>(_ obj: T) { print(obj.foo) // print(obj.bar) - Since obj does not conform to `B` I can't access ".bar" here without a forced casting. } } struct Manager: UseBProtocol { } Manager.use(test())
我想要做的是使UseBProtocol上的use函数只接受符合B. B的对象继承自A,但是当我从< T:A>更改时到< T:B>我收到一条错误消息,说Manager不符合UseAProtocol,我必须将其更改回< T:A>.
我知道我可以使用关联类型和继承协议的where子句来实现这一点 – 这就是我今天使用的 – 但是我想将通用要求移到方法中,这样我就可以将它们全部组合在同一个结构中(我有很多这个层次结构和使用关联类型我必须按层次结构使用一个结构.当条件一致性来到Swift时,这可能与关联类型有关,但直到它们……
我也可以用作!在UseBProtocol实现上强制从A转换为B,但这是一个非常糟糕的解决方案,错误只会在运行时抛出.
有没有办法实现我正在寻找的东西?
解决方法
看起来你实际上正在寻找的是UseAProtocol中的associatedType,而不是使用函数通用.
通过在UseAProtocol中声明关联类型并将使用的函数签名更改为静态函数(_ obj:ProtocolType),您的代码编译得很好,您可以从Manager访问foo和bar.
protocol AProtocol { var foo: String { get set } } protocol BProtocol: AProtocol { var bar: String { get set } } struct Test: BProtocol { var foo: String = "foo" var bar: String = "bar" } protocol UseAProtocol { associatedtype ProtocolType static func use(_ obj: ProtocolType) } protocol UseBProtocol: UseAProtocol { } extension UseBProtocol { static func use(_ obj: BProtocol) { print(obj.foo) print(obj.bar) } } struct Manager: UseBProtocol { } Manager.use(test()) //prints both "foo" and "bar"
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。