专门化协议继承的通用功能要求

时间:2018-01-22 12:20:57

标签: swift generics

我的代码中有一些协议层次结构,我有定义我使用的对象的协议和定义与这些对象一起使用的函数的协议。

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

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

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())

我想要做的是让use上的UseBProtocol函数只接受符合B的对象。 B继承自A,但当我从<T:A>更改为<T:B>时,我收到错误消息,指出经理不符合UseAProtocol而我必须更改它回到<T:A>

我知道我可以使用继承协议上的associatedtypewhere条款来实现这一点 - 这就是我今天使用的 - 但我想将通用要求移到方法中,这样我就可以对所有方法进行分组它们在同一个结构下共存(我有很多这种层次结构,使用associatedtype我必须按层次结构使用一个结构)。当有条件的一致性来到Swift时,这可能会associatedtype,但直到他们......

我也可以使用as!来强制A执行BUseBProtocol,但这是一个非常糟糕的解决方案,错误只会抛出在运行时。

有没有办法达到我想要的目的?

1 个答案:

答案 0 :(得分:0)

您实际上正在寻找的是associatedType中的UseAProtocol,而不是use函数的通用。

通过在UseAProtocol中声明关联类型并将use的函数签名更改为static func use(_ obj: ProtocolType),您的代码编译得很好,您可以同时访问foo和{{1}来自bar

Manager