Equals 2.0.0

Equals 2.0.0

测试已测试
Lang语言 SwiftSwift
许可证 MIT
发布最后发布2016 年 9 月
SPM支持 SPM

Tom Quist 维护。



Equals 2.0.0

Equals

Equals 是一个 Swift µ框架,旨在在符合 Equatable 和 Hashable 协议时减少样板代码。

需求

  • Swift 3.0
  • 任何与 Swift 3.0 兼容的平台(iOS 8.0+ / macOS X 10.10+ / tvOS 9.0+ / watchOS 2.0+ / Linux)

安装

Swift 包管理器

将其添加到您的 Package.swift 依赖关系

import PackageDescription

let package = Package(
    // ... your project details
    dependencies: [
        // As a required dependency
        .Package(url: "ssh://[email protected]/tomquist/Equals.git", majorVersion: 2)
    ],
    testDependencies: [
        // As a test dependency
        .Package(url: "ssh://[email protected]/tomquist/Equals.git", majorVersion: 2)
    ]
)

动机

我们从一个非常简单的结构体开始

struct Person {
    let firstName: String?
    let lastName: String
    let children: [Person]
}

为了使此类型符合 Equatable,我们首先必须声明遵从性,例如通过提供一个空的扩展并提供 == 操作符的重载

extension Person: Equatable {}

func ==(lhs: Person, rhs: Person) -> Bool {
    return lhs.firstName == rhs.firstName
        && lhs.lastName == rhs.lastName
        && lhs.children == rhs.children
}

如你所见,这为这样一个简单的类型写了很多代码,并且每个属性都被列出两次。

更糟的是,当遵循 Hashable 时,你还需要提供一个复杂的 hashValue 属性

extension Person: Hashable {
    var hashValue: Int {
        var result = 17
        result = 31 &* result &+ (firstName?.hashValue ?? 0)
        result = 31 &* result &+ lastName.hashValue
        for child in children {
            result = 31 &* result &+ child.hashValue
        }
        return result
    }
}

演示

使用 Equals,这变得容易得多。为了符合 Hashable,你需要做的只是遵守 EqualsHashable 协议

extension Person: EqualsHashable {
    static let hashes: Hashes<Person> = Hashes()
        .append {$0.firstName}
        .append {$0.lastName}
        .append {$0.children}
}

如果你不需要哈希功能,只需遵守 EqualsEquatable 协议即可

extension Person: EqualsEquatable {
    static let equals: Equals<Person> = Equals()
        .append {$0.firstName}
        .append {$0.lastName}
        .append {$0.children}
}

就是这样!现在你可以使用 == 操作符比较你的类型,将它放入 Set 中,或者将其用作 Dictionary 的键。

高级使用

Equals 当前提供了四种类型的属性的 append 函数

  • Equatable/Hashable 属性
  • 类型为 Equatable/HashableOptional 属性
  • 元素类型为 Equatable/HashableCollectionType 属性
  • 任何其他属性,但你必须提供 equals 和 hashValue 函数。

有时,你必须明确指定要使用哪个 append 方法。例如,让我们将上面示例中的 Personchildren 属性更改为类型 Set<Person>。因为 Set 已经遵循了 Hashable,我们现在会得到编译器错误

Ambiguous use of 'append(hashable:)'

这是因为在此情况下可能有几种可用的 append 方法。为了避免这个错误,我们可以将我们的 EqualsHashable 实现改变为以下内容

extension Person: EqualsHashable {
    static let hashes: Hashes<Person> = Hashes()
        .append {$0.firstName}
        .append {$0.lastName}
        .append(hashable: {$0.children})
}