Swift Academy · レッスン

カスタム等価性のセマンティクス

ドメインに適した等価性ルールを実装します。

レッスン 4/413 ステップ

「カスタム等価性のセマンティクス」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSwift Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Swift Academyコースには全4レッスンが含まれています。

デフォルトの==が適切でない場合

自動生成された==は、すべての格納プロパティを比較します。場合によっては厳密すぎることがあります(idだけを重視したい場合など)。逆に、十分に厳密でないこともあります。その場合は==を自分で実装します。

識別子ベースの等価性

他のフィールドを無視し、idが一致する2つのレコードを等しいものとして扱います。

struct Account: Equatable {
    let id: Int
    var balance: Int
    static func == (l: Account, r: Account) -> Bool { l.id == r.id }
}
print(Account(id: 1, balance: 10) == Account(id: 1, balance: 999))  // true

大文字と小文字を区別しない等価性

比較する前に正規化します。

struct Username: Equatable {
    let raw: String
    static func == (l: Username, r: Username) -> Bool {
        l.raw.lowercased() == r.raw.lowercased()
    }
}
print(Username(raw: "Ann") == Username(raw: "ANN"))  // true

Hashableの整合性を保つ

==をカスタマイズする場合は、同じフィールドを使うようにhash(into:)も必ず更新してください。そうしないと、等しい値のハッシュが異なり、Setが正しく動作しなくなる可能性があります。

==とhash(into:)を一致させる

どちらもidだけを使用するため、整合性が保たれています。

struct User: Hashable {
    let id: Int
    var name: String
    static func == (l: User, r: User) -> Bool { l.id == r.id }
    func hash(into h: inout Hasher) { h.combine(id) }
}
print(Set([User(id: 1, name: "A"), User(id: 1, name: "B")]).count)  // 1

キャッシュを無視する等価性

派生フィールドやキャッシュされたフィールドを比較から除外します。

struct Doc: Equatable {
    let text: String
    var cachedWordCount: Int
    static func == (l: Doc, r: Doc) -> Bool { l.text == r.text }
}
let a = Doc(text: "hi", cachedWordCount: 1)
let b = Doc(text: "hi", cachedWordCount: 999)
print(a == b)  // true

許容誤差を使った浮動小数点数の等価性

正確に一致するかではなく、許容誤差の範囲内でdoubleを比較します。

struct Measure: Equatable {
    let value: Double
    static func == (l: Measure, r: Measure) -> Bool {
        abs(l.value - r.value) < 0.0001
    }
}
print(Measure(value: 0.1 + 0.2) == Measure(value: 0.3))  // true

一部のフィールドによる等価性

ドメイン上の等価性を表すため、意味のある一部のフィールドだけを比較します。

struct Card: Equatable {
    let rank: Int
    let suit: String
    let isFaceUp: Bool   // display state, not identity
    static func == (l: Card, r: Card) -> Bool {
        l.rank == r.rank && l.suit == r.suit
    }
}
print(Card(rank: 1, suit: "H", isFaceUp: true) == Card(rank: 1, suit: "H", isFaceUp: false))  // true

Equatableの規則を守る

カスタム==は、反射律(a == a)、対称律(a == bならばb == a)、推移律を満たす必要があります。これらに違反すると、コレクションやアルゴリズムが混乱します。

対称性のある実装

正規化した形式を比較することで、対称性を保てます。

struct Email: Equatable {
    let address: String
    static func == (l: Email, r: Email) -> Bool {
        l.address.lowercased() == r.address.lowercased()
    }
}
let x = Email(address: "A@x.com")
let y = Email(address: "a@X.com")
print(x == y, y == x)  // true true

Setでのカスタム等価性

idだけを使う等価性とハッシュが一致しているため、Setは同じidを持つ値を1つとして扱います。

struct Item: Hashable {
    let id: Int
    var note: String
    static func == (l: Item, r: Item) -> Bool { l.id == r.id }
    func hash(into h: inout Hasher) { h.combine(id) }
}
let s: Set<Item> = [Item(id: 1, note: "x"), Item(id: 1, note: "y")]
print(s.count)  // 1

確認問題

一部のフィールドだけを使うカスタム==を記述した後、何をする必要がありますか。

まとめ

カスタム等価性について学びました。

  • 構造体全体を比較するデフォルトの動作が適切でない場合は、独自の==を記述します
  • よくある例は、idのみの比較、大文字と小文字を区別しない比較、浮動小数点数の許容誤差比較、キャッシュの無視です
  • 同じフィールドを使ってhash(into:)との整合性を保ちます
  • 反射律、対称律、推移律を満たします

コースは完了です。次はCustomStringConvertibleとMirrorです。

無料で開始

AI チューターと学ぶ Swift — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
122
レッスン
409

よくある質問

「カスタム等価性のセマンティクス」レッスンは無料ですか?

はい。「カスタム等価性のセマンティクス」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全4レッスンが含まれています。

「カスタム等価性のセマンティクス」で何を学びますか?

ドメインに適した等価性ルールを実装します。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Swift Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのSwift Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「カスタム等価性のセマンティクス」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このSwift Academyレッスンでコードを書いて実行できますか?

はい。すべてのSwift Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. Equatableの自動合成
  2. Hashableとhash(into:)
  3. Comparableとソート
  4. カスタム等価性のセマンティクス
← Swift Academyに戻る