swift - 使用通用 where 条件和指定参数类型有什么区别?

标签 swift function generics

<分区>

与为参数指定协议(protocol)相比,将泛型与 where 子句一起使用有什么优势,如以下函数签名所示?

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

最佳答案

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

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

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

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

前者可能更快。它也可能为函数的所有副本占用更多空间。 (但是请参阅上面关于编译器的内容。不要假设您知道在实际的优化构建中哪个会更快。)

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

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

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

关于swift - 使用通用 where 条件和指定参数类型有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57978850/

相关文章:

ios - 在场景之间传递数据 (SpriteKit)

c - 如何在不使用任何内置函数的情况下将整数转换为 C 字符串,反之亦然以及其他数据类型?

PHP set_time_limit 有效但返回 false

java - 为什么java允许在静态泛型方法中使用形式类型参数

ios - 从 'didset' JSON 解码数组数据返回 Nil 值

class - Swift 继承类

c# - 带有泛型的 NUnit 3

ios - 如何声明具有符合协议(protocol)的具体返回类型的函数?

swift - 蓝牙 retrieveConnectedPeripherals swift 需要什么 CBUUID

javascript - Uncaught ReferenceError : doit is not defined