【问题标题】:What's the difference between using a generic where condition and specifying argument type? [duplicate]使用泛型 where 条件和指定参数类型有什么区别? [复制]
【发布时间】:2019-09-17 16:56:10
【问题描述】:

与为参数指定协议相比,使用带有 where 子句的泛型有什么优势,如下面的函数签名?

func encode<T>(_ value: T) throws -> Data where T : Encodable {...}
func encode(value: Encodable) throws -> Data {...}

【问题讨论】:

    标签: swift function generics


    【解决方案1】:

    第一个是泛型​​方法,需要符合Encodable 的具体类型。这意味着对于使用不同类型的每次调用encode,可能会创建一个全新的函数副本,并仅针对该具体类型进行优化。在某些情况下,编译器可能会删除其中的一些副本,但原则上encode&lt;Int&gt;() 是与encode&lt;String&gt;() 完全不同的函数。这是一个在编译时创建函数的(通用)系统。

    相比之下,第二个是接受“可编码存在”类型参数的非泛型函数。存在是一个编译器生成的盒子,它包装了一些其他类型。原则上,这意味着值将在运行时在传递之前被复制到盒子中,如果它对于盒子来说太大,可能需要堆分配(同样,这可能不是因为编译器非常聪明,有时可以看到这是不必要的)。

    协议名称和存在名称之间的这种歧义有望在未来得到解决(并且正在讨论这样做)。将来,后一个函数有望被拼写(注意“any”):

    func encode(value: any Encodable) throws -> Data {...}
    

    前者可能更快。函数的所有副本也可能需要更多空间。 (但关于编译器,请参见上文。不要假设您知道在实际的优化构建中哪些会更快。)

    前者提供了一个真实的、具体的类型。这意味着它可以用于需要真实、具体类型的事情,例如调用静态方法或init。这意味着它可以在协议具有关联类型时使用。

    后者被装箱成一个存在,这意味着它可以存储到异构集合中。前者只能放入其特定具体类型的集合中。

    所以它们是完全不同的东西,每个都有它的目的。

    【讨论】:

      【解决方案2】:

      您可以使用多种类型约束。

      func encode<T>(encodable: T) -> Data where T: Encodable, T: Decodable {
          ...
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-14
        • 2021-04-24
        • 1970-01-01
        • 2019-08-29
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多