34

私は以下を持っていますProtocol

protocol Cacheable {
    //....//
    func identifier() -> String
}

Cacheable実装を Equatableにすることはできますか?

私が次のことをするとき:

extension Cacheable: Equatable {}

func ==(lhs:Cacheable,rhs:Cacheable) -> Bool {

     return lhs.identifier() == rhs.identifier()
}

次のエラー メッセージが表示されました:プロトコルの拡張にCacheableは継承句を含めることはできません

4

2 に答える 2

47

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に対して宣言したとおりです。EquatableCacheable==!=Cacheable

これがあなたのコードの問題ではない場合、私は実際にこの解決策を好むでしょう. プロトコルを型として扱えることは、多くの場合非常に便利です。

于 2015-08-10T14:26:21.113 に答える
11

試す。

extension Equatable where Self : Cacheable {
}
于 2015-08-10T14:23:13.267 に答える