Difference between using ObjectIdentifier() and '===' Operator

笑着哭i 提交于 2019-12-08 23:32:23

问题


Let's say I'm implementing a root class in Swift, which I declare adopts the Equatable protocol (I want to be able to tell if an array of my type contains a given instance or not).

What is the difference -if any, in this specific case- between implementing the protocol's required == operator as:

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

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

...as opposed to just doing this:

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

    return (lhs === rhs)
}

As a reference, this is what the documentation says about ObjectIdentifier():

A unique identifier for a class instance or metatype. In Swift, only class instances and metatypes have unique identities. There is no notion of identity for structs, enums, functions, or tuples.

...and this is what the "Basic Operators" section of The Swift Programming Language (Swift 3) says about the === operator:

NOTE

Swift also provides two identity operators (=== and !==), which you use to test whether two object references both refer to the same object instance. For more information, see Classes and Structures.


回答1:


There is no difference for class instance, see the following 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"
  ///

It also becomes apparent from the implementation of == for ObjectIdentifier, which just compares the pointers to the object storage:

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

which is what the === operator does as well:

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 conforms to Hashable, so it is useful if you want to implement that protocol for your class:

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

An object identifier can also be created for meta types (e.g. ObjectIdentifier(Float.self)) for which === is not defined.



来源:https://stackoverflow.com/questions/39587027/difference-between-using-objectidentifier-and-operator

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!