Swift相等性需要ObjectIdentifier吗? [英] ObjectIdentifier needed for Swift equality?

查看:65
本文介绍了Swift相等性需要ObjectIdentifier吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个自定义Swift类的实例,该实例继承自SKSpriteNode,并且能够正确执行以下代码(此问题大为简化):

We have multiple instances of a custom Swift class, which inherits from SKSpriteNode, and were able to execute the following code (grossly simplified for this question) correctly:

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 .

In other words, executing check(testInstance: instance3) returned false as expected.

但是,我们做了很多更改,并且 check 停止了工作.

However, we made a bunch of changes, and check stopped working.

CustomClass 未实现 Equatable 协议.我们只想检测唯一的实例.

CustomClass does not implement the Equatable protocol. We just want to detect unique instances.

它仅在使用 ObjectIdentifier 时才开始工作,这意味着功能已更改为:

It only started working when we used ObjectIdentifier, meaning the function changed to this:

func check(testInstance: CustomClass) -> Bool {
   return array1.filter({ ObjectIdentifier($0) == ObjectIdentifier(testInstance) }).count > 0
}

为什么需要 ObjectIdentifier ,什么时候应该使用它来实现对象相等?

Why is ObjectIdentifier needed, and when should it be used for object equality?

这是用Swift 3编写的.

This was written with Swift 3.

推荐答案

为什么需要 ObjectIdentifier ,什么时候应该使用它来实现对象相等?

Why is ObjectIdentifier needed, and when should it be used for object equality?

在这种情况下,无需使用 ObjectIdentifier 进行身份比较,您只需使用身份运算符马丁在这里说,因为类实例等效于使用 ObjectIdentifier == 重载:

You don't need to use ObjectIdentifier in order to perform an identity comparison in this case, you can simply use the identity operator === instead which, as Martin says here, for class instances is equivalent to using ObjectIdentifier's == overload:

func check(testInstance: CustomClass) -> Bool {
    return array1.contains(where: { $0 === testInstance })
}

还请注意,我们在 filter {...}.count>上使用了 contains(where:).0 ,因为前者会在找到匹配元素时短路,而后者会评估整个序列(并创建不必要的中间数组).

Also note we're using contains(where:) over filter{...}.count > 0, as the former will short-circuit upon finding a matching element, whereas the latter evaluates the entire sequence (and creates an unnecessary intermediate array).

直接使用 == 进行对象的身份比较可能有效,原因是 CustomClass 最终继承自 NSObject ,通过定义

The direct use of == to perform an identity comparison of objects may have worked due to the fact that CustomClass ultimately inherits from NSObject, which conforms to Equatable by defining an == overload that calls isEqual(_:), which by default performs an identity comparison.

但是,一般来说,应该 –可以重写 isEqual(_:)的实现,以基于属性值而不是标识进行比较.此外,在语义上 Equatable 要求 == 的实现全部基于所比较实例的可见方面(即属性值).

However in general, this should not be relied upon – the implementation of isEqual(_:) can be overridden to perform a comparison based on property values rather than identity. Furthermore, semantically Equatable requires that the implementation of == is based all on visible aspects (i.e property values) of the instances being compared.

来自文档:

平等意味着可替代性-比较的任何两个实例同样可以在依赖于它们的任何代码中互换使用价值观.为了保持可替换性, == 运算符应考虑到说明 Equatable 类型的所有可见方面.

Equality implies substitutability — any two instances that compare equally can be used interchangeably in any code that depends on their values. To maintain substitutability, the == operator should take into account all visible aspects of an Equatable type.

因此,使用 == 进行类上的身份比较永远是不正确的,即使它最初可能已经起作用.

Therefore using == for an identity comparison on your class was never correct, even though it may have worked initially.

至于何时应使用 ObjectIdentifier ,实际上您绝对不需要 just 来进行身份比较.对于类,应使用 === 运算符,对于元类型,应仅使用 == 专为它们定义的重载(在这种情况下,身份恰好发生在相等性上,因为每个新的元类型实例都是唯一的).

As for when ObjectIdentifier should be used, really you should never need it just to perform an identity comparison. For classes, you should use the === operator, and for metatypes, you should simply use the == overload defined specifically for them (as in that case, identity just happens to equality, as each new metatype instance is unique).

ObjectIdentifier 的主要用途实际上是它的 hashValue 实现,它是从初始化对象的指针值派生的.例如,在允许将元类型用作 Dictionary 键(比较制作Swift字典,其中键是类型"?).

The main use of ObjectIdentifier is really its hashValue implementation, which is derived from the pointer value of the thing that it's initialised with. This can be useful, for example, in allowing metatypes to be Dictionary keys (compare Make a Swift dictionary where the key is "Type"?).

这篇关于Swift相等性需要ObjectIdentifier吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆