1

プロジェクトでは、モデルのレイヤーにクラスを使用しているため、次のようなコードを記述する必要があります。

// MARK: - Hashable
extension Player: Hashable {
    static func == (lhs: Player, rhs: Player) -> Bool {
        return lhs.hashValue == rhs.hashValue
    }

    func hash(into hasher: inout Hasher) {
        hasher.combine(self.name)
    }
}

このボイラープレートは何とか回避できますか? デフォルトでそのEquatable比較を実装することは可能ですか? .hashValueありがとう。

4

2 に答える 2

6

これは誤りであり、コンパイラが自動的に合成しても意味がありません。

static func == (lhs: Player, rhs: Player) -> Bool {
    return lhs.hashValue == rhs.hashValue
}

同一のオブジェクトは同じハッシュ値を持つ必要がありますが、その逆ではありません。異なるオブジェクトは同じハッシュ値を持つことができます。

具体的には、あなたの例では:名前は文字列であり、無限に多くの異なる文字列がありますが、2 64の異なるハッシュ値しかありません。したがって、同じハッシュ値を持つ 2 つの異なる文字列が存在する必要があります。

すべての格納されたプロパティがあればHashable、コンパイラは適合性を完全に合成できます。例えば

struct Player : Equatable, Hashable {
    let name: String
    var score: Int
}

ここで、2 人のプレイヤーは、名前とスコアが同じであれば「同一」です。

ハッシュできないプロパティがある場合、または ID の概念をカスタマイズする場合は、それに応じてオーバーライドする必要があり== ます hash(into)。ハッシュ関数は、 で ID を決定するのと同じプロパティを使用する必要があります==。例えば

struct Player : Equatable, Hashable {
    let name: String
    var score: Int

    static func == (lhs: Player, rhs: Player) -> Bool {
        return lhs.name == rhs.name
    }

    func hash(into hasher: inout Hasher) {
        hasher.combine(self.name)
    }
}

2 人のプレイヤーが同じ名前の場合、「同一」になります。

于 2019-06-11T09:21:43.287 に答える
0

Stencil マークアップ言語を使用してカスタム テンプレートを記述し、Sourcery ライブラリを使用してコードを自動生成できます。

または、既存のソリューション (AutoEquatable、AutoHashable Sourcery テンプレート) を使用します。

また、次のように書くこともできます。

protocol IHash: class { }

extension IHash where Self: Hashable {
    static func ==(lhs: Self, rhs: Self) -> Bool {
        return lhs.hashValue == rhs.hashValue
    }
}

class User: IHash, Hashable {
    var name: String = ""

    func hash(into hasher: inout Hasher) {
        hasher.combine(self.name)
    }
}

異なるクラスでの重複を避けるのに役立ちます。

于 2019-06-11T10:41:30.027 に答える