web-dev-qa-db-ja.com

Swift StructはプロトコルEquatableに準拠していませんか?

構造をプロトコル「Equatable」に準拠させるにはどうすればよいですか?

Xcode 7.3.1を使用しています

struct MyStruct {
   var id: Int
   var value: String

   init(id: Int, value: String) {
       self.id = id
       self.value = value
   }

   var description: String {
       return "blablabla"
   }

}

「MyStruct」を使用すると、Xcodeに次のエラーが表示されます。

MyStructはプロトコル「Equatable」に準拠していません

MyStructをプロトコルに準拠させるアイデアはありますか?

18
Insou

OK、たくさんの検索の後、それは働いています...

struct MyStruct {
    var id: Int
    var value: String

    init(id: Int, value: String) {
        self.id = id
        self.value = value
    }

    var description: String {
        return "blablabla"
    }

}

extension MyStruct: Equatable {}

func ==(lhs: MyStruct, rhs: MyStruct) -> Bool {
    let areEqual = lhs.id == rhs.id &&
        lhs.value == rhs.value

    return areEqual
}

私のStructはクラスに属していたので、うまくいきませんでした。このStructをクラスから移動しました。

18
Insou

Swift 4.1(以降)更新された回答:

Swift 4.1)から開始する必要があるのは、==メソッドを実装せずに Equatable プロトコルに準拠することだけです。参照: SE-0185-等化可能およびハッシュ可能適合性の合成

例:

struct MyStruct: Equatable {
    var id: Int
    var value: String
}

let obj1 = MyStruct(id: 101, value: "object")
let obj2 = MyStruct(id: 101, value: "object")

obj1 == obj2 // true


心に留めておく==のデフォルトの動作は、タイププロパティを比較することですall例に基づいて:lhs.id == rhs.id && lhs.value == rhs.value)。カスタムの動作を実現しようとしている場合(たとえば、1つのプロパティのみを比較する場合)、自分でそれを行う必要があります。

struct MyStruct: Equatable {
    var id: Int
    var value: String
}

extension MyStruct {
    static func ==(lhs: MyStruct, rhs: MyStruct) -> Bool {
        return lhs.id == rhs.id
    }
}

let obj1 = MyStruct(id: 101, value: "obj1")
let obj2 = MyStruct(id: 101, value: "obj2")

obj1 == obj2 // true

この時点で、idの値が何であるかに関係なく、等式はvalueの値に基づきます。

26
Ahmad F

問題は、構造体がクラス内にあるということではありません。それは確かに許容され、あなたがそれをしたいかもしれない多くの例があります。問題は、Equatableプロトコルの実装にあります。 ==(実行済み)のグローバル実装を指定する必要がありますが、MyStruct ....というエンティティはありません(ParentClass.MyStructです(構造体が親クラス内で定義されている場合)。以下の例自体はおそらくこの場合の良い例ではありませんが、必要に応じてこれを行う方法を示しています。

class ParentClass {

  struct MyStruct {
    var id: Int
    var value: String

    init(id: Int, value: String) {
      self.id = id
      self.value = value
    }

    var description: String {
      return "blablabla"
    }
  }
}

extension ParentClass.MyStruct: Equatable {}

func ==(lhs: ParentClass.MyStruct, rhs: ParentClass.MyStruct) -> Bool {
  let areEqual = lhs.id == rhs.id &&
    lhs.value == rhs.value

  return areEqual
}

let s1 = ParentClass.MyStruct(id: 1, value: "one")
let s2 = ParentClass.MyStruct(id: 2, value: "two")
let s3 = ParentClass.MyStruct(id: 1, value: "one")

s1.description    //blablabla

s1 == s2         //false
s3 == s1         //true

注:並べ替えやその他の機能をサポートできるようにするため、EquatableだけでなくComparableを実装するのが好きです。

8
DJohnson