當前位置: 首頁>>編程示例 >>用法及示例精選 >>正文


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。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。