Equatable

    A type that can be compared for value equality.

    protocol Equatable
    Browse conforming types

    Types that conform to the Equatable protocol can be compared for equality using the equal-to operator (==) or inequality using the not-equal-to operator (!=). Most basic types in the Swift standard library conform to Equatable.

    Some sequence and collection operations can be used more simply when the elements conform to Equatable. For example, to check whether an array contains a particular value, you can pass the value itself to the contains(_:) method when the array’s element conforms to Equatable instead of providing a closure that determines equivalence. The following example shows how the contains(_:) method can be used with an array of strings.

    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!"

    Conforming to the Equatable Protocol

    Adding Equatable conformance to your custom types means that you can use more convenient APIs when searching for particular instances in a collection. Equatable is also the base protocol for the Hashable and Comparable protocols, which allow more uses of your custom type, such as constructing sets or sorting the elements of a collection.

    You can rely on automatic synthesis of the Equatable protocol’s requirements for a custom type when you declare Equatable conformance in the type’s original declaration and your type meets these criteria:

    • For a struct, all its stored properties must conform to Equatable.

    • For an enum, all its associated values must conform to Equatable. (An enum without associated values has Equatable conformance even without the declaration.)

    To customize your type’s Equatable conformance, to adopt Equatable in a type that doesn’t meet the criteria listed above, or to extend an existing type to conform to Equatable, implement the equal-to operator (==) as a static method of your type. The standard library provides an implementation for the not-equal-to operator (!=) for any Equatable type, which calls the custom == function and negates its result.

    As an example, consider a StreetAddress class that holds the parts of a street address: a house or building number, the street name, and an optional unit number. Here’s the initial declaration of the StreetAddress type:

    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
        }
    }

    Now suppose you have an array of addresses that you need to check for a particular address. To use the contains(_:) method without including a closure in each call, extend the StreetAddress type to conform to Equatable.

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

    The StreetAddress type now conforms to Equatable. You can use == to check for equality between any two instances or call the Equatable-constrained contains(_:) method.

    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"

    Equality implies substitutability—any two instances that compare equally can be used interchangeably in any code that depends on their values. To maintain substitutability, the == operator should take into account all visible aspects of an Equatable type. Exposing nonvalue aspects of Equatable types other than class identity is discouraged, and any that are exposed should be explicitly pointed out in documentation.

    Since equality between instances of Equatable types is an equivalence relation, any of your custom types that conform to Equatable must satisfy three conditions, for any values a, b, and c:

    • a == a is always true (Reflexivity)

    • a == b implies b == a (Symmetry)

    • a == b and b == c implies a == c (Transitivity)

    Moreover, inequality is the inverse of equality, so any custom implementation of the != operator must guarantee that a != b implies !(a == b). The default implementation of the != operator function satisfies this requirement.

    Equality is Separate From Identity

    The identity of a class instance is not part of an instance’s value. Consider a class called IntegerRef that wraps an integer value. Here’s the definition for IntegerRef and the == function that makes it conform to 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
        }
    }

    The implementation of the == function returns the same value whether its two arguments are the same instance or are two different instances with the same integer stored in their value properties. For example:

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

    Class instance identity, on the other hand, is compared using the triple-equals identical-to operator (===). For example:

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

    Requirements

    Type members

    Citizens in Swift

    Type members

    Subtypes

    Available in Distributed

    Subtypes

    Available in Cxx

    Subtypes

    Available in FoundationEssentials

    Subtypes

    Available in Foundation

    Subtypes

    Extension in _RopeModule

    Subtypes

    • protocol RopeSummary

      A commutative group that is used to augment a tree, enabling quick lookup operations.

    Extension in Crypto

    Subtypes

    Extension in NIOCore

    Subtypes

    Extension in RealModule

    Subtypes

    Extension in SwiftProtobuf

    Subtypes

    Show implementation details (1)

    Hide implementation details