- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 Swift 中子类化 NSObject
时,应该重写 hash
还是实现 Hashable
?
此外,您应该重写 isEqual:
还是实现 ==
运算符?
最佳答案
NSObject
已经符合 Hashable
协议(protocol):
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
调用 hash
方法,并且 ==
调用isEqual:
方法(来自同一协议(protocol))。 查看更新答案结束!
对于 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
设置断点或添加调试输出表明被覆盖的==
运算符永远不会被调用。我不知道这是一个错误还是预期行为。
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) // 1
print(nsSetB.count) // 1
let nsArrayB = NSArray(object: b1)
let swArrayB = [b1]
print(nsArrayB.indexOfObject(b2)) // 0
print(swArrayB.indexOf(b2)) // Optional(0)
<小时/>
更新:该行为记录在《使用 Swift 与 Cocoa 和 Objective-C》一书中的“与 Objective-C API 交互”下:
The default implementation of the
==
operator invokes theisEqual:
method, and the default implementation of the===
operator checks pointer equality. You should not override the equality or identity operators for types imported from Objective-C.The base implementation of the
isEqual:
provided by theNSObject
class is equivalent to an identity check by pointer equality. You can overrideisEqual:
in a subclass to have Swift and Objective-C APIs determine equality based on the contents of objects rather than their identities.
这本书可以在 Apple Book 应用中找到。
它也记录在 Apple 网站上,但已被删除,并且在 WebArchive snapshot 上仍然可见。页面的。
关于swift - Swift 中的 NSObject 子类 : hash vs hashValue, isEqual 与 ==,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45874901/
考虑以下代码 OCMockObject *mock = [OCMockObject mockForClass:[NSObject class]]; [[[mock expect] andReturnV
我正在尝试使用 .isEqual 比较两个对象来自 lodash-node 包的方法。即使对象相同,.isEqual返回 false . var _ = require('lodash-node');
LocalDate在 Java 中有两个类似的方法 equals和 isEqual . 它们之间有什么区别?当他们输出不同的结果时? 最佳答案 LocalDate.equals ,像大多数其他人一样
此函数检查两个对象是否具有相同的值: _.isEqual = (a, b) => { const aKeys = Object.getOwnPropertyNames(a) const bKe
const car = new Map([['100','200']]); const bike = new Map([['200','100']]); _.isEqual(car,bike); //
我正在尝试比较两种颜色,但无法得到正确的结果: 这是我的代码: NSLog(@"selfColor = %@",selfColor); NSLog(@"left = %@",left); NSLog(
背景 我有一个由第 3 方库提供的方法,它返回一个 CLBeacons 数组。 - (void)beaconManager:(ESTBeaconManager *)manager didR
Apple 的文档说如果我覆盖 isEqual: 那么我必须覆盖 hash 以确保哈希值对于被认为相等的两个对象应该相同等于: 然后我阅读了关于哈希的文档,下面是其中的一部分: Therefore,
我有一个类叫 Contact; 在Contact中我有(要测试的简单版本,还没有散列) - (BOOL)isEqual:(id)other { if (other == self)
本文整理了Java中java.time.ZonedDateTime.isEqual()方法的一些代码示例,展示了ZonedDateTime.isEqual()的具体用法。这些代码示例主要来源于Gith
我看到 Julia 有 3 种不同的方式 做平等。 == , === , 和 isequal 我应该使用哪个,何时使用? 最佳答案 ===是内在的平等。 在原语上,它是值相等:如果它们具有相同的位级表
在类中定义的方法在其他类中调用时不会被识别为函数。 文件:模型/book.model.ts export class Book { constructor(public title: stri
在类中定义的方法在其他类中调用时不会被识别为函数。 文件:模型/book.model.ts export class Book { constructor(public title: stri
我有一个使用下划线 isEqual 来比较两个 JSON 字符串的问题。目前我在主干中做了一个应用程序,我正在使用 _.isEqual(savedModel.toJSON(),changedModel
我有一个类,我用它来传递带有文本标签的选择器: @interface TableLink : NSObject @property (nonatomic, strong) NSString* name
我有一个烦人的问题,我试图解决它,但它只是没有发生,所以要么我错过了一些愚蠢的东西,要么我做错了。 基本上 id 喜欢检查一个字符串,如果它是 no,则加载空白字符串,如果还有其他内容,则加载真正的字
最近我一直在研究 java8 的新特性,以便更好地理解它们。 当尝试使用 Stream.filter 进行一些操作时,我发现了 Predicate.java 的源代码,在其中我发现了以下 isEqua
我有一个重写 isEqual 方法的人员类: #import "People.h" @implementation People @synthesize name = _name; -(BOOL)is
喜欢 class A :NSObject { let a :Int let b :UIColor } 我不想通过一一比较所有属性来实现 isEqual。如果那样,当我添加另一个属性时,
我有两个自定义 NSManagedObject 类:Notes 和 Tags。 当我覆盖 Tags 类中的 isEqual: 函数时,我收到如下错误消息: 'Class 'Tags' for enti
我是一名优秀的程序员,十分优秀!