Equatable和Comparable

上一篇:一个整数的诞生

Equatable和Comparable

上次我们谈了Swift标准库是如何通过一系列protocol来定义一个整数的,今天我们进一步深入标准库源代码,看看这些protocol的真面目。

1. Equatable

我们从最简单的Equatable开始,这是Swift标准库最基本的协议之一:

// 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表达的concept简单明了:如果一个type的实例可以比较相等性(equality),那这个type就是equatable,用Swift的语言表示就是

func ==(lhs:rhs:)

2. Comparable

Comparable表达的概念比Equatable更多了一层:除了比较相等性之外,还应该可以比较大小。

// 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协议,就必须实现这六个方法。不过不必担心,标准库已经很贴心地为其中的四个方法提供了默认的实现,用户只需要提供==<就可以了。

// 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协议
extension Date: Comparable {
    // Equatable
    // 不需要定义 !=,因为已有默认实现
    static func ==(lhs: Date, rhs: Date) -> Bool {
        return lhs.year == rhs.year && lhs.month == rhs.month
            && lhs.day == rhs.day
    }

    // Comparable
    // 不需要定义 <=, >, >=,因为已有默认实现
    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."
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容