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

前端之家收集整理的这篇文章主要介绍了Swift中的NSObject子类:hash vs hashValue,isEqual vs ==前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在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
从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.

原文链接:https://www.f2er.com/swift/320309.html

猜你在找的Swift相关文章