Swift 中“===” 和 “==”区别是什么?

19 阅读2分钟

在 Swift 中,===== 是完全不同的操作符,它们的核心区别在于比较的目标适用场景。以下是详细解释和代码案例:


一、核心区别总结

操作符比较目标适用类型是否需要自定义实现
==值是否相等值类型、引用类型需实现 Equatable
===内存地址是否相同仅引用类型(类)自动处理

二、==(值相等)

特点

  1. 比较值:检查两个实例的内容是否相等。
  2. 协议依赖:类型必须遵守 Equatable 协议,并实现 static func ==
  3. 适用范围:结构体、枚举、类(需手动实现逻辑)。

示例 1:类的值比较(手动实现 Equatable

class Student: Equatable {
    var id: Int
    var name: String
    
    init(id: Int, name: String) {
        self.id = id
        self.name = name
    }
    
    // 实现 Equatable 协议:只要 id 相同则认为相等
    static func == (lhs: Student, rhs: Student) -> Bool {
        return lhs.id == rhs.id
    }
}

let studentA = Student(id: 1, name: "Alice")
let studentB = Student(id: 1, name: "Bob") // id 相同,name 不同
let studentC = studentA

print(studentA == studentB) // true(id 相同)
print(studentA == studentC) // true(同一实例,值自然相同)

示例 2:结构体的值比较(自动合成 Equatable

struct Point: Equatable {
    var x: Int
    var y: Int
    // 结构体自动合成 Equatable 实现(所有属性都遵守 Equatable)
}

let p1 = Point(x: 3, y: 5)
let p2 = Point(x: 3, y: 5)
print(p1 == p2) // true(值完全相同)

三、===(恒等性:内存地址比较)

特点

  1. 比较内存地址:判断两个引用是否指向同一个实例
  2. 仅限引用类型:只能用于类实例(结构体、枚举无法使用)。
  3. 不可自定义:由 Swift 自动处理,开发者无法修改逻辑。

示例 1:类的实例比较

class Dog {
    var name: String
    init(name: String) { self.name = name }
}

let dog1 = Dog(name: "Buddy")
let dog2 = Dog(name: "Buddy") // 内容相同,但新实例
let dog3 = dog1

print(dog1 === dog2) // false(不同内存地址)
print(dog1 === dog3) // true(同一内存地址)

示例 2:可选类型的恒等比较

let optionalDog1: Dog? = Dog(name: "Max")
let optionalDog2: Dog? = optionalDog1 // 指向同一个实例
let optionalDog3: Dog? = Dog(name: "Max")

print(optionalDog1 === optionalDog2) // true(同一实例)
print(optionalDog1 === optionalDog3) // false(不同实例)

四、特殊案例与注意事项

案例 1:未实现 Equatable 的类无法使用 ==

class Book { // 未遵守 Equatable 协议
    var title: String
    init(title: String) { self.title = title }
}

let book1 = Book(title: "Swift Guide")
let book2 = Book(title: "Swift Guide")
// print(book1 == book2) // ❌ 编译错误:未实现 Equatable

案例 2:枚举的值比较(值类型)

enum NetworkStatus: Equatable {
    case connected
    case disconnected(reason: String)
}

let status1 = NetworkStatus.disconnected(reason: "No signal")
let status2 = NetworkStatus.disconnected(reason: "No signal")
print(status1 == status2) // true(关联值相同)

五、总结

  • ==:关注“内容”是否相等,需要类型遵守 Equatable
  • ===:关注“内存地址”是否相同,仅用于类的实例比较。