在Swift中对NSObject进行子类化时,应该覆盖哈希还是实现Hashable?另外,你应该覆盖isEqual:还是实现==?
NSObject已经符合Hashable协议:
原文链接:https://www.f2er.com/swift/320309.htmlextension 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
从NSObjectProtocol调用哈希方法,并调用==
isEqual:方法(来自相同的协议)。看到更新
答案结束!
对于NSObject子类,似乎是正确的方式
要重写hash和isEqual :,这里是一个实验
表明:
覆盖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
您可以看到,NSSet和Set都将对象视为不同的对象。
这不是理想的结果。阵列也有意想不到的结果:
let nsArrayA = NSArray(object: a1) let swArrayA = [a1] print(nsArrayA.indexOfObject(a2)) // 9223372036854775807 == NSNotFound print(swArrayA.indexOf(a2)) // nil
设置断点或添加调试输出显示被覆盖
==操作符从不调用。我不知道这是一个bug还是
意图行为。
2.覆盖哈希和isEqual:
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与可可和Objective-C”参考:
The NSObject class only performs an identity comparison,so you should implement your own isEqual: method in classes that derive from the NSObject class.
As part of implementing equality for your class,be sure to implement the hash property according to the rules in Object comparison.