使用ObjectIdentifier()和'==='运算符之间的区别

时间:2016-09-20 06:21:31

标签: swift equatable

假设我在Swift中实现了一个根类,我声明它采用Equatable协议(我希望能够判断我的类型的数组是否包含给定的实例)。

有什么区别 - 在这种特定情况下 - 在实现协议所需的==运算符之间的任何区别:

public static func ==(lhs: MyClass, rhs: MyClass) -> Bool {

    return ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
}

......而不是这样做:

public static func ==(lhs: MyClass, rhs: MyClass) -> Bool {

    return (lhs === rhs)
}

作为参考,这是文档中关于ObjectIdentifier()所说的内容:

  

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

...这就是The Swift Programming Language (Swift 3)关于===运算符的“基本运算符”部分:

  

请注意

     

Swift还提供了两个身份运算符(===!==),您可以使用它们来测试两个对象引用是否都引用同一个对象实例。有关更多信息,请参阅类和结构。

1 个答案:

答案 0 :(得分:10)

类实例没有区别,请参阅以下内容 comments in ObjectIdentifier.swift

  /// Creates an instance that uniquely identifies the given class instance.
  ///
  /// The following example creates an example class `A` and compares instances
  /// of the class using their object identifiers and the identical-to
  /// operator (`===`):
  ///
  ///     class IntegerRef {
  ///         let value: Int
  ///         init(_ value: Int) {
  ///             self.value = value
  ///         }
  ///     }
  ///
  ///     let x = IntegerRef(10)
  ///     let y = x
  ///
  ///     print(ObjectIdentifier(x) == ObjectIdentifier(y))
  ///     // Prints "true"
  ///     print(x === y)
  ///     // Prints "true"
  ///
  ///     let z = IntegerRef(10)
  ///     print(ObjectIdentifier(x) == ObjectIdentifier(z))
  ///     // Prints "false"
  ///     print(x === z)
  ///     // Prints "false"
  ///

从中也可以看出这一点 implementation of == for ObjectIdentifier, 它只是比较指向对象存储的指针:

  public static func == (x: ObjectIdentifier, y: ObjectIdentifier) -> Bool {
    return Bool(Builtin.cmp_eq_RawPointer(x._value, y._value))
  }

这是the === operator 也这样做:

public func === (lhs: AnyObject?, rhs: AnyObject?) -> Bool {
  switch (lhs, rhs) {
  case let (l?, r?):
    return Bool(Builtin.cmp_eq_RawPointer(
        Builtin.bridgeToRawPointer(Builtin.castToUnknownObject(l)),
        Builtin.bridgeToRawPointer(Builtin.castToUnknownObject(r))
      ))
  case (nil, nil):
    return true
  default:
    return false
  }
}

ObjectIdentifier符合Hashable,因此如果您想为您的班级实施该协议,这将非常有用:

extension MyClass: Hashable {
    var hashValue: Int {
        return ObjectIdentifier(self).hashValue
    }
}

还可以为元类型创建对象标识符 (例如ObjectIdentifier(Float.self)),其中未定义===