加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

swift – 专门针对协议继承的泛型函数要求

发布时间:2020-12-14 04:55:08 所属栏目:百科 来源:网络整理
导读:我的代码中有一些协议层次结构,我有定义我使用的对象的协议和定义与这些对象一起使用的函数的协议. 对象协议由其他对象协议继承,这些协议为原始协议添加了更多功能,使用它们的功能也是如此.问题是我找不到专门化函数的方法来只接受继承的参数. 这里有一些代
我的代码中有一些协议层次结构,我有定义我使用的对象的协议和定义与这些对象一起使用的函数的协议.

对象协议由其他对象协议继承,这些协议为原始协议添加了更多功能,使用它们的功能也是如此.问题是我找不到专门化函数的方法来只接受继承的参数.

这里有一些代码来澄清我正在尝试做的事情:

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"

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读