当前位置: 首页>>编程示例 >>用法及示例精选 >>正文


Swift Equatable用法及代码示例

协议

Equatable

可以比较值相等的类型。

声明

protocol Equatable

概述

可以使用等于运算符 (==) 比较符合 Equatable 协议的类型,或者使用 not-equal-to 运算符 (!=) 比较不等式。 Swift 标准库中的大多数基本类型都符合 Equatable

当元素符合 Equatable 时,可以更简单地使用一些序列和集合操作。例如,要检查数组是否包含特定值,您可以在数组元素符合 Equatable 时将值本身传递给 contains(_:) 方法,而不是提供确定等价的闭包。以下示例显示了如何将 contains(_:) 方法用于字符串数组。


let students = ["Kofi", "Abena", "Efua", "Kweku", "Akosua"]


let nameToCheck = "Kofi"
if students.contains(nameToCheck) {
    print("\(nameToCheck) is signed up!")
} else {
    print("No record of \(nameToCheck).")
}
// Prints "Kofi is signed up!"

符合平等协议

Equatable 一致性添加到您的自定义类型意味着您可以在搜索集合中的特定实例时使用更方便的 API。 Equatable 也是 HashableComparable 协议的基本协议,允许更多地使用您的自定义类型,例如构造集合或对集合的元素进行排序。

当您在类型的原始声明中声明 Equatable 一致性并且您的类型满足以下条件时,您可以依赖于自定义类型的 Equatable 协议要求的自动综合:

  • 对于 struct ,其所有存储的属性必须符合 Equatable

  • 对于 enum ,其所有关联值必须符合 Equatable 。 (即使没有声明,没有关联值的 enum 也具有 Equatable 一致性。)

要自定义类型的 Equatable 一致性,在不符合上述条件的类型中采用 Equatable,或扩展现有类型以符合 Equatable ,请实现等于运算符 ( == ) 作为您的类型的静态方法。标准库为任何 Equatable 类型提供了 not-equal-to 运算符 (!=) 的实现,它调用自定义 == 函数并否定其结果。

例如,考虑一个 StreetAddress 类,它包含街道地址的各个部分:房屋或建筑物编号、街道名称和可选的单元编号。这是 StreetAddress 类型的初始声明:


class StreetAddress {
    let number: String
    let street: String
    let unit: String?


    init(_ number: String, _ street: String, unit: String? = nil) {
        self.number = number
        self.street = street
        self.unit = unit
    }
}

现在假设您有一个地址数组,需要检查特定地址。要使用 contains(_:) 方法而不在每次调用中包含闭包,请扩展 StreetAddress 类型以符合 Equatable


extension StreetAddress: Equatable {
    static func == (lhs: StreetAddress, rhs: StreetAddress) -> Bool {
        return
            lhs.number == rhs.number &&
            lhs.street == rhs.street &&
            lhs.unit == rhs.unit
    }
}

StreetAddress 类型现在符合 Equatable 。您可以使用 == 检查任何两个实例之间的相等性或调用 Equatable -constrained contains(_:) 方法。


let addresses = [StreetAddress("1490", "Grove Street"),
                 StreetAddress("2119", "Maple Avenue"),
                 StreetAddress("1400", "16th Street")]
let home = StreetAddress("1400", "16th Street")


print(addresses[0] == home)
// Prints "false"
print(addresses.contains(home))
// Prints "true"

平等意味着可替代性——任何两个比较相等的实例都可以在取决于它们的值的任何代码中互换使用。为了保持可替代性,== 运算符应考虑 Equatable 类型的所有可见方面。不鼓励公开 Equatable 类型的非值方面而不是类标识,并且任何 are 公开的内容都应在文档中明确指出。

由于 Equatable 类型的实例之间的相等性是等价关系,因此任何符合 Equatable 的自定义类型都必须满足三个条件,对于任何值 abc

  • a == a 始终是 true(自反性)

  • a == b 暗示 b == a(对称)

  • a == bb == c 意味着 a == c(传递性)

此外,不等式是等式的逆,因此 != 运算符的任何自定义实现都必须保证 a != b 意味着 !(a == b)!= 运算符函数的默认实现满足此要求。

平等与身份是分开的

类实例的标识不是实例值的一部分。考虑一个名为IntegerRef 的类,它包含一个整数值。以下是 IntegerRef 的定义和使其符合 Equatable== 函数:


class IntegerRef: Equatable {
    let value: Int
    init(_ value: Int) {
        self.value = value
    }


    static func == (lhs: IntegerRef, rhs: IntegerRef) -> Bool {
        return lhs.value == rhs.value
    }
}

== 函数的实现返回相同的值,无论它的两个参数是相同的实例还是两个不同的实例,它们的value 属性中存储了相同的整数。例如:


let a = IntegerRef(100)
let b = IntegerRef(100)


print(a == a, a == b, separator: ", ")
// Prints "true, true"

另一方面,类实例标识使用triple-equals identical-to 运算符(===)进行比较。例如:


let c = a
print(c === a, c === b, separator: ", ")
// Prints "true, false"

可用版本

iOS 8.0+, iPadOS 8.0+, macOS 10.10+, Mac Catalyst 13.0+, tvOS 9.0+, watchOS 2.0+

相关用法


注:本文由纯净天空筛选整理自apple.com大神的英文原创作品 Equatable。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。