2024-02-16 06:00:05

==和===的差值

在swift中,似乎有两个相等运算符:双等号(==)和三重等号(===),两者之间的区别是什么?


当前回答

==用于检查两个变量是否相等 2 == 2。但是在===的情况下,它代表相等,即如果两个实例引用同一个对象示例,在类的情况下,一个引用被创建,由许多其他实例持有。

其他回答

只是一个与Any对象相关的小贡献。

我在NotificationCenter周围使用单元测试,它使用Any作为参数,我想比较是否相等。

但是,由于Any不能用于相等操作,因此有必要更改它。最终,我选择了以下方法,这让我在特定的情况下获得了平等,这里有一个简单的例子:

func compareTwoAny(a: Any, b: Any) -> Bool {
    return ObjectIdentifier(a as AnyObject) == ObjectIdentifier(b as AnyObject)
}

这个函数利用了ObjectIdentifier,它为对象提供了唯一的地址,允许我进行测试。

关于每个Apple的ObjectIdentifier,有一点需要注意:

在Swift中,只有类实例和元类型具有唯一的标识。 对于结构体、枚举、函数或 元组。

简而言之:

==运算符检查它们的实例值是否相等,"equal to"

===运算符检查引用是否指向同一个实例," same to"

长一点的回答:

Classes are reference types, it is possible for multiple constants and variables to refer to the same single instance of a class behind the scenes. Class references stay in Run Time Stack (RTS) and their instances stay in Heap area of Memory. When you control equality with == it means if their instances are equal to each other. It doesn't need to be same instance to be equal. For this you need to provide a equality criteria to your custom class. By default, custom classes and structures do not receive a default implementation of the equivalence operators, known as the “equal to” operator == and “not equal to” operator != . To do this your custom class needs to conform Equatable protocol and it's static func == (lhs:, rhs:) -> Bool function

让我们看一个例子:

class Person : Equatable {
    let ssn: Int
    let name: String

    init(ssn: Int, name: String) {
        self.ssn = ssn
        self.name = name
    }

    static func == (lhs: Person, rhs: Person) -> Bool {
        return lhs.ssn == rhs.ssn
    }
}

附注:由于ssn(社会安全号码)是一个唯一的号码,你不需要比较他们的名字是否相等。

let person1 = Person(ssn: 5, name: "Bob")
let person2 = Person(ssn: 5, name: "Bob")

if person1 == person2 {
   print("the two instances are equal!")
}

尽管person1和person2引用在Heap区域中指向两个不同的实例,但它们的实例是相等的,因为它们的ssn号码是相等的。因此输出将是两个实例相等!

if person1 === person2 {
   //It does not enter here
} else {
   print("the two instances are not identical!")
}

===运算符检查引用是否指向同一个实例," same to"。因为person1和person2在Heap区域中有两个不同的实例,所以它们不相同,两个实例的输出也不相同!

let person3 = person1

注:类是引用类型,person1的引用通过赋值操作被复制到person3,因此两个引用指向Heap区域中的同一个实例。

if person3 === person1 {
   print("the two instances are identical!")
}

它们是相同的,并且输出将是两个实例是相同的!

在Swift中,我们有===符号,这意味着两个对象都引用同一个引用同一个地址

class SomeClass {
var a: Int;

init(_ a: Int) {
    self.a = a
}

}

var someClass1 = SomeClass(4)
var someClass2 = SomeClass(4)
someClass1 === someClass2 // false
someClass2 = someClass1
someClass1 === someClass2 // true

在Objective-C和Swift中,==和!=操作符测试数值是否相等(例如,Objective-C中的NSInteger, NSUInteger, int和Swift中的int, UInt等)。对于对象(Objective-C中的NSObject/NSNumber和子类以及Swift中的引用类型),==和!=分别测试对象/引用类型是相同的东西——即相同的哈希值——或者不是相同的东西。

let a = NSObject()
let b = NSObject()
let c = a
a == b // false
a == c // true

Swift的身份相等操作符===和!==检查引用相等——因此,可能应该称为引用相等操作符IMO。

a === b // false
a === c // true

值得指出的是,Swift中的自定义引用类型(不子类化符合Equatable的类)不会自动实现equal - to操作符,但恒等操作符仍然适用。此外,通过实现==,!=将自动实现。

class MyClass: Equatable {
  let myProperty: String

  init(s: String) {
    myProperty = s
  }
}

func ==(lhs: MyClass, rhs: MyClass) -> Bool {
  return lhs.myProperty == rhs.myProperty
}

let myClass1 = MyClass(s: "Hello")
let myClass2 = MyClass(s: "Hello")
myClass1 == myClass2 // true
myClass1 != myClass2 // false
myClass1 === myClass2 // false
myClass1 !== myClass2 // true

这两种语言都没有为其他类型(如结构)实现这些相等操作符。但是,可以在Swift中创建自定义操作符,例如,可以创建一个操作符来检查CGPoint的相等性。

infix operator <==> { precedence 130 }
func <==> (lhs: CGPoint, rhs: CGPoint) -> Bool {
  return lhs.x == rhs.x && lhs.y == rhs.y
}

let point1 = CGPoint(x: 1.0, y: 1.0)
let point2 = CGPoint(x: 1.0, y: 1.0)
point1 <==> point2 // true

例如,如果你创建一个类的两个实例,例如myClass:

var inst1 = myClass()
var inst2 = myClass()

你可以比较这些例子,

if inst1 === inst2

引用:

用于测试两个对象引用是否都引用 相同的对象实例。

摘自:苹果公司《快速编程语言》。“iBooks。https://itun.es/sk/jEUH0.l