1)Cacheable
同じ型の 2 つの を比較できるようにする
protocol Cacheable: Equatable {
//....//
func identifier() -> String
}
func ==<T : Cacheable>(lhs: T, rhs: T) -> Bool {
return lhs.identifier() == rhs.identifier()
}
長所
これが最も簡単な解決策です。
短所
Cacheable
同じタイプの 2 つのオブジェクトのみを比較できます。Animal
これは、以下のコードが失敗することを意味し、それを修正するには、次のコードに準拠させる必要がありますCacheable
。
class Animal {
}
class Dog: Animal,Cacheable {
func identifier() -> String {
return "object"
}
}
class Cat: Animal,Cacheable {
func identifier() -> String {
return "object"
}
}
let a = Dog()
let b = Cat()
a == b //such comparison is not allowed
2)Cacheable
任意のタイプの s を比較できるようにする
protocol Cacheable:Equatable {
//....//
func identifier() -> String
}
func ==<T:Cacheable>(lhs: T, rhs: T) -> Bool {
return lhs.identifier() == rhs.identifier()
}
func !=<T:Cacheable>(lhs: T, rhs: T) -> Bool {
return lhs.identifier() != rhs.identifier()
}
func ==<T:Cacheable, U:Cacheable>(lhs: T, rhs: U) -> Bool {
return lhs.identifier() == rhs.identifier()
}
func !=<T:Cacheable, U:Cacheable>(lhs: T, rhs: U) -> Bool {
return lhs.identifier() != rhs.identifier()
}
長所
上記のソリューション 1 の制限を取り除きます。これで、 と を簡単に比較できDog
ますCat
。
短所
- 実装は長くなります。実際、
==
関数だけを指定するだけでは不十分な理由はわかりません。これは、コンパイラのバグである可能性があります。とにかく、 と の両方の実装を提供する必要が==
あり!=
ます。
- 場合によっては、この実装の利点が問題を引き起こす可能性があります。これは、まったく異なるオブジェクト間の比較を許可していて、コンパイラが完全に問題ないためです。
3) 準拠せずにEquatable
protocol Cacheable {
//....//
func identifier() -> String
}
func ==(lhs: Cacheable, rhs: Cacheable) -> Bool {
return lhs.identifier() == rhs.identifier()
}
func !=(lhs: Cacheable, rhs: Cacheable) -> Bool {
return lhs.identifier() != rhs.identifier()
}
長所
Cacheable
ジェネリックを必要とせずに型として使用できます。これにより、まったく新しい可能性が広がります。例えば:
let c:[Cacheable] = [Dog(),RaceCar()]
c[0] == c[1]
c[0] != c[1]
ソリューション 1 と 2 では、そのようなコードは失敗し、クラスでジェネリックを使用する必要があります。ただし、最新の実装Cacheable
では型として扱われるため、型の配列を宣言できます[Cacheable]
。
短所
への準拠を宣言しなくなったため、パラメータEquatable
を受け入れる関数は を受け入れません。明らかに、sに対して宣言したとおりです。Equatable
Cacheable
==
!=
Cacheable
これがあなたのコードの問題ではない場合、私は実際にこの解決策を好むでしょう. プロトコルを型として扱えることは、多くの場合非常に便利です。