在 Swift 中,===
和 ==
是完全不同的操作符,它们的核心区别在于比较的目标和适用场景。以下是详细解释和代码案例:
一、核心区别总结
操作符 | 比较目标 | 适用类型 | 是否需要自定义实现 |
---|---|---|---|
== | 值是否相等 | 值类型、引用类型 | 需实现 Equatable |
=== | 内存地址是否相同 | 仅引用类型(类) | 自动处理 |
二、==
(值相等)
特点
- 比较值:检查两个实例的内容是否相等。
- 协议依赖:类型必须遵守
Equatable
协议,并实现static func ==
。 - 适用范围:结构体、枚举、类(需手动实现逻辑)。
示例 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(值完全相同)
三、===
(恒等性:内存地址比较)
特点
- 比较内存地址:判断两个引用是否指向同一个实例。
- 仅限引用类型:只能用于类实例(结构体、枚举无法使用)。
- 不可自定义:由 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
。===
:关注“内存地址”是否相同,仅用于类的实例比较。