「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战」
检查两个对象或值是否相等绝对是所有编程中最常执行的操作之一。 因此,在本文中,让我们看看 Swift 如何对相等概念进行建模,以及该模型如何在值类型和引用类型之间变化。
Swift 实现相等性的一个最有趣的方面是它都是以一种非常面向协议的方式完成的——这意味着任何类型都可以通过符合 Equatable 协议来变得可相等,可以这样完成:
在上面的示例中,我们符合 Equatable 的方式是实现 == 运算符的重载,它接受两个要比较的值(lhs,左侧值,rhs,右侧值), 然后它返回一个关于这两个值是否应该被认为相等的布尔结果。
不过,好消息是我们通常不必自己编写那种 == 运算符重载,因为只要类型的存储属性本身都是 Equatable 时,编译器就能够自动合成这样的实现。 所以在上面的 Article 类型的情况下,我们实际上可以删除我们手动的相等检查代码,并简单地使该类型看起来像这样:
Swift 的相等性检查是如此面向协议的事实也为我们在使用泛型类型时提供了强大的功能。 例如,符合 Equatable 的值的集合(例如 Array 或 Set)也自动被认为是等价的——我们不需要任何额外的代码:
此类集合相等性检查的工作方式是通过 Swift 的条件一致性功能,该功能使类型仅在满足某些条件时才符合特定协议。 例如,只有当存储在给定数组中的元素也符合 Equatable 时,Swift 的 Array 类型才符合 Equatable 类型——这使我们可以检查两个 Article 数组是否被视为相等 :
由于上述逻辑都没有硬编码到编译器本身,如果我们想让我们自己的泛型类型也有条件地等价,我们也可以使用完全相同的基于条件一致性的技术。 例如,我们的代码库可能包含某种形式的 Group 类型,可用于标记一组相关值:
为了使该 Group 类型在用于存储 Equatable 值时符合 Equatable ,我们只需编写以下空扩展名,它看起来与我们在上面看到的 Array 扩展名几乎相同:
完成上述操作后,我们现在可以检查两个基于 Article 的 Group 值是否相等,就像我们在使用数组时一样:
就像集合一样,当 Swift 元组的存储值都符合 Equatable 时,也可以检查它们的相等性:
但是,包含上述类型的等价元组的集合不会自动符合等价元组。 因此,如果我们将上述两个元组放入两个相同的数组中,那么它们就不会被认为是等价的:
上述不起作用的原因(至少不是开箱即用的)是因为 - 就像发出的编译器消息一样 - 元组不能符合协议,这意味着我们采用的 Equatable-conforming Array 扩展 早点看是不会生效的。
但是,有一种方法可以使上述工作正常进行,虽然我意识到以下通用代码可能不属于标记为“基础”的文章中,但我仍然认为值得快速查看一下——因为它只是说明了 Swift 的相等检查是多么灵活,而且我们不仅限于实现单个 == 重载以符合 Equatable。
因此,如果我们要添加另一个自定义 == 重载,特别是对于包含相等的二元素元组的数组,那么上面的代码示例实际上会成功编译: