swift Equatable
2022-05-29 本文已影响0人
tom__zhu
我来了,swift
定义
用于做值类型对比的协议。
适用范围
遵循Equatable的类型都可以使用==
或是!=
符号对比判断。这个类型包括struct
/class
/enum
实现原理
任何遵循Equatable的类型,都需要实现方法static func ==(lhs: Self, rhs: Self) -> Bool
在这个方法内按照指定的值和值间对比关系返回true
或是false
,外部表现为==
或是!=
的结果
struct Human: Equatable {
var name: String
var age = 5
static func == (lhs: Self, rhs: Self) -> Bool {
return lhs.name == rhs.name
}
}
let tom = Human(name: "tom", age: 5)
let tim = Human(name: "tim", age: 6)
tom == tim // false
let man1 = Human(name: "tom", age: 5)
let man2 = Human(name: "tom", age: 6)
man1 == man2 // true
Human对Equatable方法定义为只判断name属性是否值相同,即使age属性不同,man1==man2结果是true
在不同类型中的差异
- class遵循Equatable必须要实现
static func ==(lhs: Self, rhs: Self) -> Bool
方法。但是,struct遵循Equatable可以不用实现static func ==(lhs: Self, rhs: Self) -> Bool
方法,默认将struct实例中所有属性对比并返回与
结果
struct Dog: Equatable {
var name: String
var age = 0
}
let dog1 = Dog(name: "tom", age: 1)
let dog2 = Dog(name: "tom", age: 1)
dog1 == dog2 // true
let dog3 = Dog(name: "tom", age: 1)
let dog4 = Dog(name: "tom", age: 2)
dog3 == dog4 // false
struct Dog遵循Equatable协议但没有实现协议方法其实例dog1与dog2实例相等,dog3与dog3实例不相等
- 数组等容器类(数组/字典等)内部的元素需要遵循Equatable才能实现一些能力,例如contains(_:)
let students = ["Kofi", "Abena", "Efua", "Kweku", "Akosua"]
let nameToCheck = "Kofi"
if students.contains(nameToCheck) {
print("\(nameToCheck) is signed up!") // Prints "Kofi is signed up!"
} else {
print("No record of \(nameToCheck).")
}
- swift standard library中的大部分基础类型默认已经遵循Equatable,例如Int/Array/Dictionary/Set
- struct重的属性如果有不遵守Equatable,那么其实例无法用
==
class MyClassNoEquatable {
}
struct NoEquatableStruct: Equatable {
var mc = MyClassNoEquatable()
}
let nes1 = NoEquatableStruct()
let nes2 = NoEquatableStruct()
nes1 == nes2
上面代码会报错,提示Type 'NoEquatableStruct' does not conform to protocol 'Equatable'
协议间的关联
Hashable协议基于Equatable协议,对于struct遵守Hashable并不需要实现Equatable方法,但是对于class遵守Hashable必须要实现Equatable的方法
Comparable协议基于Equatable
==
与===
- Equatable本质是对属性的值对比,适用范围有struct/class/enum
-
===
是对class实例指针的对比,且仅适用于class实例
class IntegerRef: Equatable {
let value: Int
init(_ value: Int) {
self.value = value
}
static func == (lhs: IntegerRef, rhs: IntegerRef) -> Bool {
return lhs.value == rhs.value
}
}
let a = IntegerRef(100)
let b = IntegerRef(100)
print(a == a, a == b, separator: ", ") // Prints "true, true"
let c = a
print(c === a, c === b, separator: ", ") // Prints "true, false"