Equatable, Hashable, Comparable

10/15/2020 Swift

[toc]

# Equatable

对自定义结构体、枚举、类使用相等运算符(==、!=)时,需要遵守该协议。

注:只需要实现 ==运算符即可(!=== 的逆运算)

//协议定义
static func == (lhs: Self, rhs: Self) -> Bool
static func != (lhs: Self, rhs: Self) -> Bool

//示例
class IntegerRef: Equatable {
    let value: Int
    init(_ value: Int) {
        self.value = value
    }

  	//实现 == 运算符函数
    static func == (lhs: IntegerRef, rhs: IntegerRef) -> Bool {
        return lhs.value == rhs.value
    }
}

# 自动合成

当结构体、枚举显式声明遵守Equatable后,以下情况会自动合成 == 运算符函数:

  • 结构体,所有存储属性都遵守 Equatable协议
  • 枚举,所有的关联值都遵守 Equatable协议
struct 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
    }
}

//显式声明遵守 Equatable协议,隐式自动合成 == 运算符函数
extension StreetAddress : Equatable {
    
}

# Comparable

比较运算符函数:<, <=, >=, >,Comparable 继承自 Equatable。

自定义时,只需要需要实现 <, == (其他运算符函数(<=, >=, >)系统会自动实现)。

struct Date {
    let year: Int
    let month: Int
    let day: Int
}

// Comparable 只需要实现 <, == 两个运算符函数
extension Date: Comparable {
  	//实现 <
    static func < (lhs: Date, rhs: Date) -> Bool {
        if lhs.year != rhs.year {
            return lhs.year < rhs.year
        } else if lhs.month != rhs.month {
            return lhs.month < rhs.month
        } else {
            return lhs.day < rhs.day
        }
    }
  
  	// Comparable 继承自 Equatable,所以必须实现 ==
    static func == (lhs: Date, rhs: Date) -> Bool {
      return lhs.year == rhs.year && lhs.month == rhs.month
          && lhs.day == rhs.day
    }
}

# Hashable

# Hasher

Hasher是Swift提供的哈希函数,根据输入值产出一个唯一的哈希值



var hasher = Hasher()
//feed
hasher.combine(23)
hasher.combine("Hello")
//产出哈希值,Int类型
let hashValue = hasher.finalize()

# Hashable

哈希协议,继承自Equatable,必须实现 ==hash(into hasher: inout Hasher) 方法。


struct GridPoint {
    var x: Int
    var y: Int
}


extension GridPoint: Hashable {
  
  	//实现 == 运算符函数
    static func == (lhs: GridPoint, rhs: GridPoint) -> Bool {
        return lhs.x == rhs.x && lhs.y == rhs.y
    }

  	//实现 hash方法,注意这里只需要调用combine方法即可
    func hash(into hasher: inout Hasher) {
        hasher.combine(x)
        hasher.combine(y)
    }
}

# 自动合成

当显式声明Hashable后,满足以下条件会实现自动合成

  • 结构体,所有存储属性都遵守 Hashable协议
  • 枚举,所有的关联值都遵守 Hashable协议

延伸参考:nshipster-hashable (opens new window)

# Identifiable

用于对类的实例变量进行ID标示

A class of types whose instances hold the value of an entity with stable identity.

protocol Identifiable {
    associatedtype ID: Hashable
    var id: ID { get }
}

延伸参考:nshipster-identifiable (opens new window)

# Tuple Comparison

# Equatable

Swift对元组实现了2-6个元素的比较,超过6个则无法比较,必须自定义比较方法。

注:对元组也可以用 <, <=, >, >=比较运算符

思考一个问题,能否对元组进行extension,使其可以对七个元素进行比较?

答案是不能。Swift中结构类型有两种:named typescompound typesnamed types 分为结构体、枚举、类、协议, compound types分为函数和元组。extension只能对named types进行扩展。

参考:

# Comparable

元组实现了2-6个元素的 比较运算符函数<, <=, >=, >

Last Updated: 10/14/2020, 8:09:29 PM