==和===之间的区别

Fel*_*len 288 swift

在swift中似乎有两个相等运算符:double equals(==)和triple equals(===),两者之间有什么区别?

agl*_*ser 245

!==并且===是身份运算符,用于确定两个对象是否具有相同的引用.

Swift还提供了两个标识运算符(===和!==),用于测试两个对象引用是否都引用同一个对象实例.

摘录自:Apple Inc."The Swift Programming Language."iBooks.https://itun.es/us/jEUH0.l

  • 对.来自ObjC,`==`是`isEqual:`,或类定义的语义等价.Swift中的`===`是(Obj)中的`=='C - 指针相等或对象标识. (48认同)
  • 至少有两种方法可以考虑语言如何定义值类型与内存.一个是名称与值的每个绑定(`var`或`let`)是唯一的副本 - 因此创建指针是没有意义的,因为您指向的值与您首次创建的值不同.另一个是Swift对值语义的定义抽象了存储 - 编译器可以自由地进行优化,直到并且包括永远不会将值存储在可以在其使用的行之外访问的存储器位置(寄存器,指令编码等). (2认同)

Fat*_*ksu 123

简而言之:

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

=== operator检查引用是否指向同一个实例, "identical to"

答案很长:

类是引用类型,多个常量和变量可以在后台引用类的同一单个实例.类引用保留在运行时堆栈(RTS)中,它们的实例保留在内存的堆区域中.当你用==它控制相等时,意味着它们的实例彼此相等.它不需要是相同的实例是相等的.为此,您需要为自定义类提供相等条件.默认情况下,自定义类和结构不接收等价运算符的默认实现,称为"等于"运算符==和"不等于"运算符!=.要做到这一点,您的自定义类需要符合Equatable协议及其static func == (lhs:, rhs:) -> Bool功能

我们来看看例子:

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
    }
}
Run Code Online (Sandbox Code Playgroud)

P.S.: 由于ssn(社会安全号码)是唯一号码,因此您无需比较其名称是否相等.

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

if person1 == person2 {
   print("the two instances are equal!")
}
Run Code Online (Sandbox Code Playgroud)

虽然person1和person2引用指向Heap区域中的两个不同实例,但它们的实例是相同的,因为它们的ssn数相等.所以输出将是the two instance are equal!

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

===operator检查引用是否指向同一个实例"identical to".由于person1和person2在Heap区域中有两个不同的实例,因此它们与输出不同the two instance are not identical!

let person3 = person1
Run Code Online (Sandbox Code Playgroud)

P.S: 类是引用类型,person1的引用通过此赋值操作复制到person3,因此两个引用都指向堆区域中的相同实例.

if person3 === person1 {
   print("the two instances are identical!")
}
Run Code Online (Sandbox Code Playgroud)

它们是相同的,输出将是 the two instances are identical!


Sco*_*ner 62

在这两种Objective-C和夫特中,==!=运营商的测试用于数值的值相等(例如,NSInteger,NSUInteger,int,在Objective-C和Int,UInt等在SWIFT).对于对象(Objective中的NSObject/NSNumber和子类以及Swift中的引用类型),==!=测试对象/引用类型是相同的相同的东西 - 即相同的哈希值 - 或者不是相同的相同的东西,分别.

let a = NSObject()
let b = NSObject()
let c = a
a == b // false
a == c // true
Run Code Online (Sandbox Code Playgroud)

Swift的身份相等运算符,===!==检查引用相等 - 因此,应该可以称为引用相等运算符IMO.

a === b // false
a === c // true
Run Code Online (Sandbox Code Playgroud)

值得指出的是,Swift中的自定义引用类型(不是符合Equatable的类的子类)不会自动实现等于运算符,但是身份相等运算符仍然适用.此外,通过实施==,!=自动实施.

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
Run Code Online (Sandbox Code Playgroud)

这些相等运算符不是为其他类型实现的,例如任何一种语言的结构.但是,可以在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
Run Code Online (Sandbox Code Playgroud)

  • 抱歉,但是在Obj-C中,==运算符不会比较EQUALITY,而是像C一样比较指针引用(对象标识). (3认同)

Jak*_*lář 44

在快速3及以上

===(或!==)

  • 检查值是否相同 (都指向相同的内存地址).
  • 比较参考类型.
  • 就像==在Obj-C(指针相等)中一样.

==(或!=)

  • 检查值是否相同.
  • 比较值类型.
  • isEqual:Obj-C行为中的默认值一样.

这里我比较三个实例 (类是引用类型)

class Person {}

let person = Person()
let person2 = person
let person3 = Person()

person === person2 // true
person === person3 // false
Run Code Online (Sandbox Code Playgroud)

  • 到目前为止,这个帖子最简洁的答案 (4认同)

Pat*_*tru 37

Swifts的微妙之处===不仅仅是指针算术.在Objective-C中,您可以比较任何两个指针(即NSObject *),==这在Swift中不再正确,因为类型在编译期间起着更大的作用.

游乐场会给你

1 === 2                    // false
1 === 1                    // true
let one = 1                // 1
1 === one                  // compile error: Type 'Int' does not conform to protocol 'AnyObject'
1 === (one as AnyObject)   // true (surprisingly (to me at least))
Run Code Online (Sandbox Code Playgroud)

使用字符串我们将不得不习惯这个:

var st = "123"                                 // "123"
var ns = (st as NSString)                      // "123"
st == ns                                       // true, content equality
st === ns                                      // compile error
ns === (st as NSString)                        // false, new struct
ns === (st as AnyObject)                       // false, new struct
(st as NSString) === (st as NSString)          // false, new structs, bridging is not "free" (as in "lunch")
NSString(string:st) === NSString(string:st)    // false, new structs
var st1 = NSString(string:st)                  // "123"
var st2 = st1                                  // "123"
st1 === st2                                    // true
var st3 = (st as NSString)                     // "123"
st1 === st3                                    // false
(st as AnyObject) === (st as AnyObject)        // false
Run Code Online (Sandbox Code Playgroud)

但是你也可以玩得如下:

var st4 = st             // "123"
st4 == st                // true
st4 += "5"               // "1235"
st4 == st                // false, not quite a reference, copy on write semantics
Run Code Online (Sandbox Code Playgroud)

我相信你能想到更多有趣的案例:-)

Swift 3的更新(正如JakubTruhlář的评论所示)

1===2                                    // Compiler error: binary operator '===' cannot be applied to two 'Int' operands
(1 as AnyObject) === (2 as AnyObject)    // false
let two = 2
(2 as AnyObject) === (two as AnyObject)  // false (rather unpleasant)
(2 as AnyObject) === (2 as AnyObject)    // false (this makes it clear that there are new objects being generated)
Run Code Online (Sandbox Code Playgroud)

这看起来更加一致Type 'Int' does not conform to protocol 'AnyObject',但是我们得到了

type(of:(1 as AnyObject))                // _SwiftTypePreservingNSNumber.Type
Run Code Online (Sandbox Code Playgroud)

但明确的转换表明可能会发生一些事情.在字符串方面,NSString只要我们仍然可以使用import Cocoa.然后我们会有

var st = "123"                                 // "123"
var ns = (st as NSString)                      // "123"
st == ns                                       // Compile error with Fixit: 'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?
st == ns as String                             // true, content equality
st === ns                                      // compile error: binary operator '===' cannot be applied to operands of type 'String' and 'NSString'
ns === (st as NSString)                        // false, new struct
ns === (st as AnyObject)                       // false, new struct
(st as NSString) === (st as NSString)          // false, new structs, bridging is not "free" (as in "lunch")
NSString(string:st) === NSString(string:st)    // false, new objects
var st1 = NSString(string:st)                  // "123"
var st2 = st1                                  // "123"
st1 === st2                                    // true
var st3 = (st as NSString)                     // "123"
st1 === st3                                    // false
(st as AnyObject) === (st as AnyObject)        // false
Run Code Online (Sandbox Code Playgroud)

它仍然是混乱有两个String类,但是在丢弃隐式转换可能会使其成为一个更溢于言表.

  • 您不能使用“ ===”运算符来比较“整数”。不在Swift 3中。 (2认同)

jm6*_*666 12

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

var inst1 = myClass()
var inst2 = myClass()
Run Code Online (Sandbox Code Playgroud)

你可以比较这些实例,

if inst1 === inst2
Run Code Online (Sandbox Code Playgroud)

引用:

用于测试两个对象引用是否都引用同一对象实例.

摘录自:Apple Inc."The Swift Programming Language."iBooks.https://itun.es/sk/jEUH0.l


dar*_*ara 11

在Swift中我们有=== simbol这意味着两个对象都指的是相同的引用相同的地址

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
Run Code Online (Sandbox Code Playgroud)