身份運算符的左側和右側不是對象而是類型。
其實,在蘋果平臺上,他們都是對象。
這是由於Swift類在底層實現爲Objective-C類,因爲Mike Ash詳細描述了in this great blog post。這意味着一個類的元類型是也是一個Objective-C類,因此符合01。
正因爲如此,你可以用身份操作比較類元類型,因爲它的定義爲:
public func ===(lhs: AnyObject?, rhs: AnyObject?) -> Bool
它會比較兩個對象是否是同一個對象,或者特別是在這種情況下,相同的類metatype。
相比之下,值類型的元類型不是Objective-C對象 - 它只是指向某些靜態元數據的指針。如果我們重寫你的榜樣使用struct
:
struct Dog {}
let d = Dog()
// Binary operator '===' cannot be applied to two 'Dog.Type' operands
if type(of: d) === Dog.self {
print("yep")
}
你會看到,我們可以不再使用===
比較元類型,因爲它們不符合AnyObject
。實際上,使用身份運算符來比較類元類型的能力只是它們作爲Objective-C對象實現的副作用。
比較元類型的普遍方法是用等號運算符==
,如雨燕專門爲元類型提供了一個過載:
public func ==(t0: Any.Type?, t1: Any.Type?) -> Bool
此檢查兩個元類型是否是一樣的,但是,不像===
,它的工作原理與均爲類元類型和值類型的元類型。在引擎蓋下,它執行as a simple pointer comparison,所以應該總是產生與===
一樣的結果,並帶有元類型。
因此,我總是建議您將元數據類型與==
進行比較,因爲您並不依賴與AnyObject
的一致性。例如,在Linux平臺上,class metatypes don't conform to AnyObject
因此不能與身份運算符進行比較(儘管有趣的是,當導入Foundation
時,似乎爲AnyObject.Type
操作數增加了===
重載 - 可能有助於互操作性)。
感謝您的善意幫助:) – SLN