Associated value付きのenumにIdentifiableを準拠させる

開発環境

$ swift --version
swift-driver version: 1.62.15 Apple Swift version 5.7.1 (swiftlang-5.7.1.135.3 clang-1400.0.29.51)
Target: x86_64-apple-macosx13.0

モチベーション

こんなコードを書くとコンパイラに怒られる。

// Type 'CustomColor' does not conform to protocol 'Identifiable'
enum CustomColor: Identifiable {
    case red
    case blue
    case green(Int)
    
    var id: Self { self }
}

怒られないようにしたい。

アプローチ

XcodeDo you want to add protocol stubs? で自動修正を頼むと、以下になって解決しない。

enum CustomColor: Identifiable {
    var id: ObjectIdentifier  // 追加
    
    case red
    case blue
    case green(CustomGreen)
    
    var id: Self { self }
}

おそらく、Associated valueがあるときに自身を返すだけではidの型であるObjectIdentifierを満たせないのだろう。

いくらかやり方はありそうで、

import Foundation

enum CustomColor: Identifiable {
    case red
    case blue
    case green(Int)
    
    var id: UUID { UUID() }
}

乱暴にUUIDのインスタンスを返すことで一旦はコンパイラには怒られない。しかし、idアクセス毎にUUIDのインスタンスを生成しているのでパフォーマンスが悪そう。

別案として、素直にHashableに準拠させてあげれば上記よりは筋が良さそう。

enum CustomColor: Identifiable, Hashable {
    case red
    case blue
    case green(Int)
    
    var id: Self { self }
}

Associated valueの型であるIntはHashableに準拠しているし、enum自体も自身を返してあげればIdentifiableに準拠できるため明示的にenum自体に一意性を担保させてあげる必要性が分かっていないけど丁寧にやってあげる必要がある、ということが分かった。

参考