【问题标题】:Swift generic type conforming to a variable subset of protocolsSwift 泛型类型符合协议的可变子集
【发布时间】:2016-07-02 02:06:30
【问题描述】:

我正在试验协议以及如何使用它们来解耦代码,同时利用使用协议的其他副作用。基本上,我想做的是以下几点:

一个示例可以是按范围分组到协议中的 API 调用的超集(例如“用户 API 调用”和“设置 API 调用”,或“非可变 API 调用”和“可变 API 调用”)。在这种情况下,有兴趣使用A 公开的API 的消费者不一定知道BC 的API。

考虑以下模仿上述场景的协议:

protocol A {}
protocol B {}
protocol C {}

然后,给定一组协议[A, B, C],使用工厂类,我想要一个符合这些协议子集的 API 对象实例:

let a = Factory<A>.create()
let ab = Factory<A, B>.create()
let bc = Factory<B, C>.create()

我已经尝试了一些实现,例如:

class Factory<T: protocol<A, B, C>> {
    class func create() -> T {
        return ...
    }
}

但是,使用 let a = Factory&lt;A&gt;.create() 进行初始化会产生以下错误:

不支持将“A”用作符合协议“A”的具体类型

如果工厂定义为:

class Factory<T where T: A, T: B>

有几件事显然失败了:

  • &lt;T: protocol&lt;A, B, C&gt;&gt;&lt;T where T: A, T: B&gt; 要求返回的对象同时符合 ABC,而不仅仅是它们的子集。
  • 鉴于该错误,似乎甚至不可能“将协议用作符合协议的具体类型”。

简而言之,是否有可能实现我想要的目标?

【问题讨论】:

    标签: swift generics


    【解决方案1】:

    在你的情况下,我会放弃使用泛型,我可能还会考虑协议继承。

    因此,例如,可变协议将从不可变协议继承,因为您希望能够以最低限度访问,并在备用情况下访问和更改。

    协议的目的是将您从底层实现类中抽象出来。在您的示例中,泛型并没有真正增加这种能力。您的工厂(或多个工厂)可以简单地提供许多创建方法,这些方法返回符合各种协议的对象。

    继续使用泛型意味着暴露底层实现类,这就是导致错误的原因。你不能为此使用协议,因为它不是具体的,它只是一些具体对象将要提供的定义。

    【讨论】:

    • 我同意对于可变/不可变示例,协议继承是首选,但对于另一个示例,我认为不是。根据我的经验,将相关行为分组到所描述的协议中是一种常见的方法。但是,可能不希望为每个协议组合(a、b、c、ab、ac、bc、abc)提供创建函数。无论如何,是否正确理解我不能仅通过协议(&lt;A&gt;)使用泛型,但我需要一个类型,然后我可以要求它符合给定协议(&lt;T where T: A&gt;)?
    • 确实,选择从哪里继承,不要只是让一切都继承。您可以使用协议定义泛型,但不能使用协议实例化它,因为它不是具体的。
    • 我明白了,谢谢你的澄清。你认为这是 Swift 的限制吗?如果是这样,这种限制的原因是什么?在我看来,“我可以拥有一些符合此协议的对象吗”这个问题并不是没有道理的。
    • 不是限制,是要求,泛型需要知道具体类型才能工作,否则它应该如何满足定义?在某些时候,您需要一个实际的具体实例来使用,当您创建一个泛型实例时,这就是重点。
    猜你喜欢
    • 2014-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多