gpt4 book ai didi

swift - Swift中的NSObject子类:hash vs hashValue,isEqual vs ==

转载 作者:行者123 更新时间:2023-11-30 10:32:12 33 4
gpt4 key购买 nike

在Swift中为NSObject子类化时,您应该重写哈希还是实现Hashable?此外,你应该重载isEqual:或实现==?

最佳答案

NSObject已经符合所述Hashable协议:

extension NSObject : Equatable, Hashable {
/// The hash value.
///
/// **Axiom:** `x == y` implies `x.hashValue == y.hashValue`
///
/// - Note: the hash value is not guaranteed to be stable across
/// different invocations of the same program. Do not persist the
/// hash value across program runs.
public var hashValue: Int { get }
}

public func ==(lhs: NSObject, rhs: NSObject) -> Bool


我找不到官方参考,但似乎 hashValue
hash调用 NSObjectProtocol方法,而 ==调用
isEqual:方法(来自相同协议)。请参阅更新
答案的结尾!

对于 NSObject子类,正确的方法似乎是
覆盖 hashisEqual:,这是一个实验
证明:

1.覆盖 hashValue==

class ClassA : NSObject {
let value : Int

init(value : Int) {
self.value = value
super.init()
}

override var hashValue : Int {
return value
}
}

func ==(lhs: ClassA, rhs: ClassA) -> Bool {
return lhs.value == rhs.value
}


现在创建该类的两个不同实例
“等于”并将它们放在集合中:

let a1 = ClassA(value: 13)
let a2 = ClassA(value: 13)

let nsSetA = NSSet(objects: a1, a2)
let swSetA = Set([a1, a2])

print(nsSetA.count) // 2
print(swSetA.count) // 2


如您所见, NSSetSet都将对象视为不同的对象。
这不是期望的结果。数组也有意外的结果:

let nsArrayA = NSArray(object: a1)
let swArrayA = [a1]

print(nsArrayA.indexOfObject(a2)) // 9223372036854775807 == NSNotFound
print(swArrayA.indexOf(a2)) // nil


设置断点或添加调试输出可发现已覆盖
永远不会调用 ==运算符。我不知道这是错误还是
预期的行为。

2.覆盖 hashisEqual:

class ClassB : NSObject {
let value : Int

init(value : Int) {
self.value = value
super.init()
}

override var hash : Int {
return value
}

override func isEqual(object: AnyObject?) -> Bool {
if let other = object as? ClassB {
return self.value == other.value
} else {
return false
}
}
}


对于Swift 3, isEqual:的定义更改为

override func isEqual(_ object: Any?) -> Bool { ... }


现在所有结果均符合预期:

let b1 = ClassB(value: 13)
let b2 = ClassB(value: 13)

let nsSetB = NSSet(objects: b1, b2)
let swSetB = Set([b1, b2])

print(swSetB.count) // 1
print(nsSetB.count) // 1

let nsArrayB = NSArray(object: b1)
let swArrayB = [b1]

print(nsArrayB.indexOfObject(b2)) // 0
print(swArrayB.indexOf(b2)) // Optional(0)




更新:该行为现已记录在
Interacting with Objective-C APIs
在“将Swift与Cocoa和Objective-C一起使用”参考中:


  NSObject类仅执行身份比较,因此您应该在从NSObject类派生的类中实现自己的isEqual:方法。
  
  作为为类实现相等性的一部分,请确保根据对象比较中的规则实现hash属性。

关于swift - Swift中的NSObject子类:hash vs hashValue,isEqual vs ==,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58934382/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com