栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

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

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

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
子类,正确的方法似乎是重写
hash
isEqual:
,这是一个实验,证明了这一点:

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) // 2print(swSetA.count) // 2

正如你所看到的,

NSSet
并且
Set
治疗的对象不同。这不是期望的结果。数组也有意外的结果:

let nsArrayA = NSArray(object: a1)let swArrayA = [a1]print(nsArrayA.indexOfObject(a2)) // 9223372036854775807 == NSNotFoundprint(swArrayA.indexOf(a2)) // nil

设置断点或添加调试输出表明,

==
永远不会调用覆盖的 运算符。我不知道这是错误还是预期的行为。

2.覆盖
hash
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) // 1print(nsSetB.count) // 1let nsArrayB = NSArray(object: b1)let swArrayB = [b1]print(nsArrayB.indexOfObject(b2)) // 0print(swArrayB.indexOf(b2)) // Optional(0)

更新: 该行为现在在 “与Swift与Cocoa和Objective-C一起使用”参考中与Objective-C
API交互中进行
了记录 :

NSObject类仅执行身份比较,因此您应该在从NSObject类派生的类中实现自己的isEqual:方法。

作为为类实现相等性的一部分,请确保根据对象比较中的规则实现hash属性。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/436395.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号