我们有一个自定义 Swift 类的多个实例,它继承自 SKSpriteNode,并且能够正确执行以下代码(针对此问题进行了大幅简化):
let instance1 = CustomClass()
let instance2 = CustomClass()
let instance3 = CustomClass()
let instance4 = CustomClass()
let array1 = [instance1, instance2]
let array2 = [instance3, instance4]
func check(testInstance: CustomClass) -> Bool {
return array1.filter({ $0 == testInstance }).count > 0
}
check(testInstance: instance3)
换句话说,执行check(testInstance: instance3)
回false
正如预期的那样。
然而,我们做了很多改变,并且check
停止工作。
CustomClass
不执行Equatable
协议。我们只想检测独特的实例。
当我们使用时它才开始工作ObjectIdentifier
,这意味着函数更改为:
func check(testInstance: CustomClass) -> Bool {
return array1.filter({ ObjectIdentifier($0) == ObjectIdentifier(testInstance) }).count > 0
}
Why is ObjectIdentifier
需要什么,什么时候应该使用它来实现对象相等?
这是用 Swift 3 编写的。
Why is ObjectIdentifier
需要什么,什么时候应该使用它来实现对象相等?
你不需要使用ObjectIdentifier
为了在这种情况下执行恒等比较,您可以简单地使用恒等运算符===相反,作为马丁在这里说,对于类实例相当于使用ObjectIdentifier
's ==
超载:
func check(testInstance: CustomClass) -> Bool {
return array1.contains(where: { $0 === testInstance })
}
另请注意我们正在使用contains(where:)
over filter{...}.count > 0
,因为前者在找到匹配元素时会短路,而后者会评估整个序列(并创建不必要的中间数组)。
直接使用==
执行对象的身份比较may已经起作用,因为CustomClass
最终继承自NSObject
,符合Equatable
通过定义an ==超载那个叫isEqual(_:),默认情况下执行身份比较。
但一般来说,这应该not可以依赖——实施isEqual(_:)
可以重写以根据属性值而不是身份来执行比较。此外,从语义上Equatable
要求实施==
基于正在比较的实例的所有可见方面(即属性值)。
From 文档:
平等意味着可替代性——任何两个比较的实例
同样可以在任何依赖于它们的代码中互换使用
价值观。为了保持可替代性,==
操作员应考虑
考虑一个事物的所有可见方面Equatable
type.
因此使用==
因为对你的班级进行身份比较从来都是不正确的,尽管它最初可能有效。
至于什么时候ObjectIdentifier
应该使用,实际上你永远不需要它just进行身份比较。对于类,您应该使用===
运算符,对于元类型,您应该简单地使用==专门为它们定义的重载(在这种情况下,身份恰好等于相等,因为每个新元类型实例都是唯一的)。
主要用途ObjectIdentifier
确实是它的hashValue
实现,它派生自初始化对象的指针值。这可能很有用,例如,允许元类型Dictionary
键(比较制作一个 Swift 字典,其中键是“Type”?).
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)