11

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 では、クラス インスタンスとメタタイプのみが一意の ID を持ちます。構造体、列挙型、関数、またはタプルの同一性の概念はありません。

...そして、これはThe Swift Programming Language (Swift 3)の「Basic Operators」セクションがオペレーターについて述べていること===です:

ノート

Swift は 2 つの同一性演算子 (===および!==) も提供します。これを使用して、2 つのオブジェクト参照が両方とも同じオブジェクト インスタンスを参照しているかどうかをテストします。詳細については、クラスと構造体を参照してください。

4

1 に答える 1

15

クラス インスタンスに違いはありません 。 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"
  ///

また 、 forの実装==ObjectIdentifierからも明らかです。これは、ポインタをオブジェクト ストレージと比較するだけです。

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

これは===オペレーター も同様に行うことです。

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)ていないメタ タイプ ( など) に対しても作成できます。===

于 2016-09-20T06:57:35.630 に答える