web-dev-qa-db-ja.com

Swiftプロトコルは赤道を実装しています

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

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

CacheableでEquatableを実装できますか?

私が次のことをしたとき:

extension Cacheable: Equatable {}

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

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

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

34
Bobj-C

1)同じタイプの2つのCacheablesを比較できるようにする

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

func ==<T : Cacheable>(lhs: T, rhs: T) -> Bool {
    return lhs.identifier() == rhs.identifier()
}

長所

これが最も簡単なソリューションです。

短所

同じタイプの2つのCacheableオブジェクトのみを比較できます。これは、以下のコードが失敗することを意味し、それを修正するにはAnimalCacheableに準拠させる必要があります。

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)比較するCacheablesを許可します

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の上記の制限を削除しました。これで、DogCatを簡単に比較できます。

短所

  • 実装はより長くなります。実際、==関数のみを指定するだけでは十分ではない理由はわかりません。これはコンパイラーのバグかもしれません。とにかく、==!=の両方の実装を提供する必要があります。
  • 場合によっては、この実装の利点が問題を引き起こす可能性があります。これは、まったく異なるオブジェクト間の比較を許可しているため、コンパイラーはそれでまったく問題ありません。

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への適合を宣言しなくなったため、Equatableパラメーターを受け入れる関数はCacheableを受け入れません。明らかに、==および!=は別として、Cacheablesに対して宣言しました。

これがコードの問題でない場合は、実際にこのソリューションをお勧めします。プロトコルをタイプとして扱うことができることは、多くの場合非常に便利です。

46

やってみて。

extension Equatable where Self : Cacheable {
}
11
njuri