2016-09-20 6 views
6

Equatableプロトコルを採用すると宣言しているSwiftでルートクラスを実装しているとしましょう(自分のタイプの配列に含まれているかどうかを知りたい与えられたインスタンスかどうか)。ObjectIdentifier()と '==='の使用の違い

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

    return (lhs === rhs) 
} 
:反対はちょうどこれを行うためにと...

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

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

:任意の-if違いのように、プロトコルの必要==オペレータを実装する間、この特定の大文字では、どのような


参考資料として、これはObjectIdentifier()についてのドキュメントです。

クラスインスタンスまたはメタタイプの一意の識別子。 Swiftでは、クラスインスタンスとメタタイプは一意のIDを持っています。 構造体、列挙型、関数、またはタプルのIDの概念については、 はありません。

...これはThe Swift Programming Language (Swift 3)の "基本的な演算子" セクションでは、===オペレータについてこう言われる、

NOTE

スウィフトは、2つのアイデンティティ演算子(===!==)を提供し、 2つのオブジェクト参照が両方とも同じオブジェクトインスタンスを参照しているかどうかをテストするために使用します。詳細については、「クラスと構造体」を参照してください。

答えて

8

クラスのインスタンスの違いはありません、以下 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 するESとしても:あなたのクラスにそのプロトコルを実装する場合、それは便利ですので

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))の場合、===が定義されていません。

+0

非常に詳細な回答ありがとうございます。私は自分のクラスのタイプに大きな違いはないと思っていましたが、これは非常に啓発的です。私はSwiftがオープンソースであるので、ソースコードを自分でチェックするべきだと思っていたはずです。 –

+1

'==='演算子[今すぐ直接比較する](https://github.com/apple/swift/blob/b330c6078fd233ea7206158a20b21b4672d75cc3/stdlib/public/core/Equatable.swift#L249)パラメータの 'ObjectIdentifier'。 – execv

関連する問題