【问题标题】:Difference between using ObjectIdentifier() and '===' Operator使用 ObjectIdentifier() 和 '===' 运算符之间的区别
【发布时间】:2017-01-27 23:04:06
【问题描述】:

假设我在 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 还提供了两个身份运算符(===!==),您可以使用它们来测试两个对象引用是否都引用同一个对象实例。有关详细信息,请参阅类和结构。

【问题讨论】:

    标签: swift equatable


    【解决方案1】:

    类实例没有区别,见下文 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))未定义===

    【讨论】:

    • 感谢您非常详细的回答。我期望我自己的班级类型没有太大的不同,但这非常有启发性。既然 Swift 是开源的,我应该考虑自己检查源代码!
    • === operator now directly compares ObjectIdentifier 参数。
    猜你喜欢
    • 2011-05-24
    • 2016-05-18
    • 2011-10-22
    • 2012-10-06
    • 2010-12-30
    • 2019-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多