Swift结构体不符合协议Equatable?

30

如何使一个结构符合协议 "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符合该协议吗?

4个回答

48

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


请记住==的默认行为是比较所有类型属性(基于例如:lhs.id == rhs.id && lhs.value == rhs.value)。如果你想要实现定制行为(例如只比较一个属性),你必须自己处理:

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 的值是什么。


1
这将是大多数人今后提出这个问题的正确答案。 - Aaron Frary

25

好的,在经过大量搜索之后,它正在工作中...

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
}

我的结构体在类中,所以它不起作用...我将这个结构体移到类外面,现在它很好 :)


2
请参考DJohnson的回答:问题不在于是否在类中。 - Cannoliopsida

8
问题并不在于结构体位于类内部。这是完全允许的,在许多情况下你可能希望这样做。问题在于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

注意:我喜欢实现Comparable而不仅仅是Equatable,这将使您能够支持排序和其他功能。

如何使其更通用?这样我就可以在所有的类和结构中使用它。 - macky12345

-4

Class和Struct是不同的。Struct是值类型,而Class是引用类型。

你不能在Class中定义Struct。相反地,在Struct中也不能定义Class。

Struct和Class都可以符合任何协议,包括自定义协议。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接