据我所知,标识操作符用于确定两个对象是否具有相同的引用。这意味着,在实践中,操作者的两边都是一个物体。
但是,我尝试了下面的代码,它使我对我所理解的身份操作符的功能感到困惑。
class Dog {}
let d: Dog = Dog()
if type(of: d) === Dog.self {
print("yep") //prints out "yep"
}
if type(of: d) == Dog.self {
print("yep") //prints out "yep"
}
标识运算符的左右两边不是一个对象,而是一个类型,在这一点上,语义等价运算符和对象标识运算符(看起来)的工作方式是相同的。
问题:
这是一个错误,还是我没有正确理解整个要点。
谢谢你的帮助和时间
最佳答案
标识运算符的左侧和右侧不是对象,而是类型。
实际上,在苹果平台上,它们是对象。
这是因为swift类在hood下被实现为objective-c类,正如mike ash详细介绍的那样。这意味着类的元类型也是一个Objective-C类,因此符合AnyObject
。
因此,可以将类元类型与标识运算符进行比较,因为它的定义如下:
public func ===(lhs: AnyObject?, rhs: AnyObject?) -> Bool
它将比较这两个对象是同一对象,还是在本例中是同一类元类型。
相反,在幕后,值类型的元类型不是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
。因此,实际上,使用Identity运算符比较类元类型的能力只是它们作为Objective-C对象实现的一个副作用。比较元类型的通用方法是使用相等运算符,因为swift为元类型提供了一个专门的重载:
public func ==(t0: Any.Type?, t1: Any.Type?) -> Bool
这将检查两个元类型是否相同,但是与
==
不同,它同时处理类元类型和值类型元类型。在hood下,它被实现了,所以应该总是产生与类元类型相同的结果。因此,我始终建议将元类型与
===
进行比较,因为您不依赖于与===
的一致性。例如,在Linux平台上,in this great blog post因此不能与标识操作符进行比较(尽管有趣的是,当导入==
时,它似乎为AnyObject
操作数添加了一个AnyObject
重载,这可能有助于互操作性)。关于swift - 身份运算符还可以检查命名类型是否相同而不仅仅是引用等于,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43224682/