我们有一个自定义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
}
为什么需要ObjectIdentifier
,何时应该将它用于对象相等?
这是用Swift 3编写的。
答案 0 :(得分:2)
为什么需要
ObjectIdentifier
,何时应该将它用于对象相等?
在这种情况下,您不需要使用ObjectIdentifier
来执行身份比较,您只需使用身份运算符===
代替Martin says here,对于类实例,相当于使用ObjectIdentifier
' s ==
重载:
func check(testInstance: CustomClass) -> Bool {
return array1.contains(where: { $0 === testInstance })
}
另请注意,我们使用contains(where:)
而不是filter{...}.count > 0
,因为前者会在找到匹配元素时发生短路,而后者会评估整个序列(并创建不必要的中间数组) )。
直接使用==
执行对象的身份比较可能已经有效,因为CustomClass
最终继承自NSObject
,这符合Equatable
通过定义调用an ==
overload的isEqual(_:)
来isEqual(_:)
,默认情况下执行身份比较。
但是一般情况下,这应该不依赖 - 可以覆盖Equatable
的实现,以基于属性值而不是标识执行比较。此外,语义==
要求==
的实现基于所比较实例的可见方面(即属性值)。
平等意味着可替代性 - 任何两个比较的实例 同样可以在任何依赖于它们的代码中互换使用 值。为了保持可替代性,
Equatable
运算符应该考虑到 帐户==
类型的所有可见方面。
因此,在您的课程中使用ObjectIdentifier
进行身份比较从来都不正确,即使它最初可能有效。
至于应该使用===
的时候,你真的应该永远不需要只是来进行身份比较。对于类,您应该使用ObjectIdentifier
运算符,对于元类型,您应该只使用专门为它们定义的==
重载(因为在这种情况下,身份恰好相等,因为每个新的元类型实例是独一无二的。)
hashValue
的主要用途实际上是它的Dictionary
实现,它是从它初始化的东西的指针值派生而来的。这可能很有用,例如,允许元类型为Array ( [0] => WC_Memberships_User_Membership Object ( [id] => 148489 [plan_id] => 148071 [plan] => WC_Memberships_Membership_Plan Object ( [id] => 148071 [name] => Groups **[slug] => groups** [post] => WP_Post Object ( [ID] => 148071 [post_author] => 1 [post_date] => 2017-05-12 11:15:21 [post_date_gmt] => 2017-05-12 10:15:21 [post_content] => [post_title] => Groups [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => groups [to_ping] => [pinged] => [post_modified] => 2017-05-12 11:48:07 [post_modified_gmt] => 2017-05-12 10:48:07 [post_content_filtered] => [post_parent] => 0 [guid] => http://dev3.benefacto.org/?post_type=wc_membership_plan&p=148071 [menu_order] => 0 [post_type] => wc_membership_plan [post_mime_type] => [comment_count] => 0 [filter] => raw ) [access_method_meta:protected] => _access_method [default_access_method:protected] => unlimited [access_length_meta:protected] => _access_length [access_start_date_meta:protected] => _access_start_date [access_end_date_meta:protected] => _access_end_date [product_ids_meta:protected] => _product_ids [members_area_meta:protected] => _members_area_sections [email_content_meta:protected] => _email_content [rules:WC_Memberships_Membership_Plan:private] => Array ( ) ) [user_id] => 12312800 [status] => wcm-active [post] => WP_Post Object ( [ID] => 148489 [post_author] => 12312800 [post_date] => 2017-05-28 00:04:02 [post_date_gmt] => 2017-05-27 23:04:02 [post_content] => [post_title] => Auto Draft [post_excerpt] => [post_status] => wcm-active [comment_status] => closed [ping_status] => closed [post_password] => um_592a05dbb3501 [post_name] => auto-draft-2 [to_ping] => [pinged] => [post_modified] => 2017-05-28 00:04:02 [post_modified_gmt] => 2017-05-27 23:04:02 [post_content_filtered] => [post_parent] => 148071 [guid] => http://dev3.benefacto.org/?post_type=wc_user_membership&p=148489 [menu_order] => 0 [post_type] => wc_user_membership [post_mime_type] => [comment_count] => 0 [filter] => raw ) [product:WC_Memberships_User_Membership:private] => [type:protected] => manually-assigned [start_date_meta:protected] => _start_date [end_date_meta:protected] => _end_date [cancelled_date_meta:protected] => _cancelled_date [paused_date_meta:protected] => _paused_date [paused_intervals_meta:protected] => _paused_intervals [product_id_meta:protected] => _product_id [order_id_meta:protected] => _order_id [previous_owners_meta:protected] => _previous_owners ) [1] => WC_Memberships_User_Membership Object ( [id] => 148483 [plan_id] => 148169 [plan] => WC_Memberships_Membership_Plan Object ( [id] => 148169 [name] => London **[slug] => london** [post] => WP_Post Object ( [ID] => 148169 [post_author] => 1 [post_date] => 2017-05-14 11:12:52 [post_date_gmt] => 2017-05-14 10:12:52 [post_content] => [post_title] => London [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => closed [post_password] => [post_name] => london [to_ping] => [pinged] => [post_modified] => 2017-05-15 18:17:18 [post_modified_gmt] => 2017-05-15 17:17:18 [post_content_filtered] => [post_parent] => 0 [guid] => http://dev3.benefacto.org/?post_type=wc_membership_plan&p=148169 [menu_order] => 0 [post_type] => wc_membership_plan [post_mime_type] => [comment_count] => 0 [filter] => raw ) [access_method_meta:protected] => _access_method [default_access_method:protected] => unlimited [access_length_meta:protected] => _access_length [access_start_date_meta:protected] => _access_start_date [access_end_date_meta:protected] => _access_end_date [product_ids_meta:protected] => _product_ids [members_area_meta:protected] => _members_area_sections [email_content_meta:protected] => _email_content [rules:WC_Memberships_Membership_Plan:private] => Array ( ) ) [user_id] => 12312800 [status] => wcm-active [post] => WP_Post Object ( [ID] => 148483 [post_author] => 12312800 [post_date] => 2017-05-24 15:34:16 [post_date_gmt] => 2017-05-24 14:34:16 [post_content] => [post_title] => [post_excerpt] => [post_status] => wcm-active [comment_status] => open [ping_status] => closed [post_password] => um_592599e82db15 [post_name] => 148483 [to_ping] => [pinged] => [post_modified] => 2017-05-24 15:34:16 [post_modified_gmt] => 2017-05-24 14:34:16 [post_content_filtered] => [post_parent] => 148169 [guid] => http://dev3.benefacto.org/?post_type=wc_user_membership&p=148483 [menu_order] => 0 [post_type] => wc_user_membership [post_mime_type] => [comment_count] => 0 [filter] => raw ) [product:WC_Memberships_User_Membership:private] => [type:protected] => manually-assigned [start_date_meta:protected] => _start_date [end_date_meta:protected] => _end_date [cancelled_date_meta:protected] => _cancelled_date [paused_date_meta:protected] => _paused_date [paused_intervals_meta:protected] => _paused_intervals [product_id_meta:protected] => _product_id [order_id_meta:protected] => _order_id [previous_owners_meta:protected] => _previous_owners ) )
个键(比较Make a Swift dictionary where the key is "Type"?)。