==和===之间的区别

时间:2014-06-02 20:35:13

标签: swift

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

11 个答案:

答案 0 :(得分:241)

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

  

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

摘自:Apple Inc.“The Swift Programming Language。”iBooks。 https://itun.es/us/jEUH0.l

答案 1 :(得分:86)

简而言之:

== 操作员检查其实例值是否相等, "equal to"

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

长答案:

类是引用类型,多个常量和变量可以在后台引用同一个类的单个实例。类引用保留在运行时堆栈(RTS)中,它们的实例保留在内存的堆区域中。当您使用 == 控制相等性时,这意味着他们的实例是否彼此相等。它不需要是相同的实例是相等的。为此,您需要为自定义类提供相等条件。默认情况下,自定义类和结构不会接收等价运算符的默认实现,称为“等于”运算符 == 和“不等于”运算符 {{ 1}} 。为此,您的自定义类需要符合 != 协议,并且 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 } } 由于ssn(社会安全号码)是唯一号码,因此您无需比较其姓名是否相等。

P.S.:

尽管person1和person2引用了Heap区域中的两个不同实例,但它们的实例是相同的,因为它们的ssn数相等。因此输出将为let person1 = Person(ssn: 5, name: "Bob") let person2 = Person(ssn: 5, name: "Bob") if person1 == person2 { print("the two instances are equal!") }

the two instance are equal!

if person1 === person2 { //It does not enter here } else { print("the two instances are not identical!") } 运算符会检查引用是否指向同一个实例 === 。由于person1和person2在Heap区域中有两个不同的实例,因此它们不相同且输出"identical to"

the two instance are not identical!

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

P.S:

它们是相同的,输出将是if person3 === person1 { print("the two instances are identical!") }

答案 2 :(得分:62)

在Objective-C和Swift中,==!=运算符测试数值的值相等性(例如NSIntegerNSUInteger,{{1} },在Objective-C和Swift中的intInt等。对于对象(Objective中的NSObject / NSNumber和子类以及Swift中的引用类型),UInt==测试对象/引用类型是否相同 - 即相同的哈希值 - - 或者分别是相同的东西。

!=

Swift的身份相等运算符,let a = NSObject() let b = NSObject() let c = a a == b // false a == c // true ===,检查引用相等性 - 因此,应该称为引用相等运算符IMO。

!==

值得指出的是,Swift中的自定义引用类型(不是类似于Equatable的类的子类)不会自动实现等于运算符,但身份相等运算符仍然适用。此外,通过实施a === b // false a === c // true ==会自动实施。

!=

这些相等运算符不是针对其他类型实现的,例如任何一种语言的结构。但是,可以在Swift中创建自定义运算符,例如,可以创建运算符来检查CGPoint的相等性。

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

答案 3 :(得分:40)

在swift 3及以上

===(或!==

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

==(或!=

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

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

class Person {}

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

person === person2 // true
person === person3 // false

答案 4 :(得分: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))

使用字符串我们必须习惯这个:

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

但是你也可以获得如下乐趣:

var st4 = st             // "123"
st4 == st                // true
st4 += "5"               // "1235"
st4 == st                // false, not quite a reference, copy on write semantics

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

更新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)

这看起来与Type 'Int' does not conform to protocol 'AnyObject'更加一致,但我们接着

type(of:(1 as AnyObject))                // _SwiftTypePreservingNSNumber.Type

但明确的转换表明可能会发生一些事情。 只要我们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

有两个String类仍然令人困惑,但删除隐式转换可能会使 little 更明显。

答案 5 :(得分:12)

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

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

您可以比较这些实例,

if inst1 === inst2

专利:

  

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

摘自:Apple Inc.“The Swift Programming Language。”iBooks。 https://itun.es/sk/jEUH0.l

答案 6 :(得分: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

答案 7 :(得分:4)

只是与Any对象相关的次要贡献。

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

但是,由于Any不能在相等操作中使用,因此有必要对其进行更改。最后,我采用了以下方法,这使我在特定情况下得到了平等,这里用一个简单的例子显示:

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

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

在上述链接中,每个Apple关于ObjectIdentifier的一个项目需要注意:

  

在Swift中,只有类实例和元类型具有唯一标识。   结构,枚举,功能或者结构没有身份概念   元组。

答案 8 :(得分:1)

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

答案 9 :(得分:0)

Swift 4:另一个使用 Unit Tests 的示例,仅适用于===

注意:下面的测试失败,==,可以使用===

func test_inputTextFields_Delegate_is_ViewControllerUnderTest() {

        //instantiate viewControllerUnderTest from Main storyboard
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        viewControllerUnderTest = storyboard.instantiateViewController(withIdentifier: "StoryBoardIdentifier") as! ViewControllerUnderTest 
        let _ = viewControllerUnderTest.view

        XCTAssertTrue(viewControllerUnderTest.inputTextField.delegate === viewControllerUnderTest) 
    }

班级正在

class ViewControllerUnderTest: UIViewController, UITextFieldDelegate {
    @IBOutlet weak var inputTextField: UITextField!

    override func viewDidLoad() {
        super.viewDidLoad()
        inputTextField.delegate = self
    }
}

如果使用==,则单元测试中的错误为Binary operator '==' cannot be applied to operands of type 'UITextFieldDelegate?' and 'ViewControllerUnderTest!'

答案 10 :(得分:0)

  • 值相等

    • Objective-C:isEqual:
    • 迅速:==
  • 引用相等

    • Objective-C:==
    • 迅速:===

了解更多here