Equatable和Comparable
上次我們談了Swift標(biāo)準(zhǔn)庫是如何通過一系列protocol來定義一個整數(shù)的,今天我們進(jìn)一步深入標(biāo)準(zhǔn)庫源代碼,看看這些protocol的真面目。
1. Equatable
我們從最簡單的Equatable開始,這是Swift標(biāo)準(zhǔn)庫最基本的協(xié)議之一:
// file: Equatable.swift
public protocol Equatable {
static func == (lhs: Self, rhs: Self) -> Bool
}
extension Equatable {
@_inlineable
@_transparent
public static func != (lhs: Self, rhs: Self) -> Bool {
return !(lhs == rhs)
}
}
Equatable表達(dá)的concept簡單明了:如果一個type的實(shí)例可以比較相等性(equality),那這個type就是equatable,用Swift的語言表示就是
func ==(lhs:rhs:)
2. Comparable
Comparable表達(dá)的概念比Equatable更多了一層:除了比較相等性之外,還應(yīng)該可以比較大小。
// file: Comparable.swift
public protocol Comparable : Equatable {
static func < (lhs: Self, rhs: Self) -> Bool
static func <= (lhs: Self, rhs: Self) -> Bool
static func >= (lhs: Self, rhs: Self) -> Bool
static func > (lhs: Self, rhs: Self) -> Bool
}
Comparable一共定義了六個方法(別忘了還有兩個繼承自Equatable),也就是說一個type要是遵從Comparable協(xié)議,就必須實(shí)現(xiàn)這六個方法。不過不必?fù)?dān)心,標(biāo)準(zhǔn)庫已經(jīng)很貼心地為其中的四個方法提供了默認(rèn)的實(shí)現(xiàn),用戶只需要提供==和<就可以了。
// file: Comparable.swift
extension Comparable {
@_inlineable
public static func > (lhs: Self, rhs: Self) -> Bool {
return rhs < lhs
}
@_inlineable
public static func <= (lhs: Self, rhs: Self) -> Bool {
return !(rhs < lhs)
}
@_inlineable
public static func >= (lhs: Self, rhs: Self) -> Bool {
return !(lhs < rhs)
}
}
3. 一個例子
我們通過一個例子來說明Comparable的用法,這個例子取自Swift官方文檔:
// 一個自定義類型
struct Date {
let year: Int
let month: Int
let day: Int
}
// 我們希望Date遵從Comparable協(xié)議
extension Date: Comparable {
// Equatable
// 不需要定義 !=,因為已有默認(rèn)實(shí)現(xiàn)
static func ==(lhs: Date, rhs: Date) -> Bool {
return lhs.year == rhs.year && lhs.month == rhs.month
&& lhs.day == rhs.day
}
// Comparable
// 不需要定義 <=, >, >=,因為已有默認(rèn)實(shí)現(xiàn)
static func <(lhs: Date, rhs: Date) -> Bool {
if lhs.year != hrs.year {
return lhs.year < rhs.year
} else if lhs.month != rhs.month {
return lhs.month < rhs.month
} else {
return lhs.day < rhs.day
}
}
}
let spaceOddity = Date(year: 1969, month: 7, day: 11)
let moonLanding = Date(year: 1969, month: 7, day: 20)
if moonLanding > spaceOddify {
print("Major Tom stepped through the door first.")
} else {
print("David Bowie was following in Neil Armstrong's footsteps.")
}
// Prints "Major Tom stepped through the door first."