カスタム等価性のセマンティクス
ドメインに適した等価性ルールを実装します。
「カスタム等価性のセマンティクス」は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")) // trueHashableの整合性を保つ
==をカスタマイズする場合は、同じフィールドを使うように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)) // trueEquatableの規則を守る
カスタム==は、反射律(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 trueSetでのカスタム等価性
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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- Equatableの自動合成
- Hashableとhash(into:)
- Comparableとソート
- カスタム等価性のセマンティクス