gpt4 book ai didi

objective-c - 覆盖 isEqual : and hash 的最佳实践

转载 作者:IT老高 更新时间:2023-10-28 12:13:57 26 4
gpt4 key购买 nike

如何在 Objective-C 中正确地覆盖 isEqual:? “捕获”似乎是如果两个对象相等(由 isEqual: 方法确定),它们必须具有相同的哈希值。

Introspection Cocoa Fundamentals Guide 的部分确实有一个关于如何覆盖 isEqual: 的示例,复制如下,用于名为 MyWidget 的类:

- (BOOL)isEqual:(id)other {
if (other == self)
return YES;
if (!other || ![other isKindOfClass:[self class]])
return NO;
return [self isEqualToWidget:other];
}

- (BOOL)isEqualToWidget:(MyWidget *)aWidget {
if (self == aWidget)
return YES;
if (![(id)[self name] isEqual:[aWidget name]])
return NO;
if (![[self data] isEqualToData:[aWidget data]])
return NO;
return YES;
}

它检查指针相等,然后是类相等,最后使用 isEqualToWidget: 比较对象,它只检查 namedata 属性.示例没有展示的是如何覆盖hash

假设还有其他不影响相等性的属性,比如 age。不应该重写 hash 方法,使得只有 namedata 影响哈希?如果是这样,你会怎么做?只需添加 namedata 的哈希?例如:

- (NSUInteger)hash {
NSUInteger hash = 0;
hash += [[self name] hash];
hash += [[self data] hash];
return hash;
}

够了吗?有没有更好的技术?如果你有像 int 这样的原语怎么办?将它们转换为 NSNumber 以获取它们的哈希?或者像 NSRect 这样的结构?

(Brain fart:最初将它们与|=一起写成“按位或”。意思是添加。)

最佳答案

开始

 NSUInteger prime = 31;
NSUInteger result = 1;

那么对于你所做的每一个原语

 result = prime * result + var

对于对象,您使用 0 表示 nil,否则使用它们的哈希码。

 result = prime * result + [var hash];

对于 bool 值,您使用两个不同的值

 result = prime * result + ((var)?1231:1237);

解释和归属

这不是 tcurdt 的作品,评论要求更多解释,所以我认为编辑署名是公平的。

该算法在《Effective Java》一书中得到普及,the relevant chapter can currently be found online here .那本书普及了该算法,现在该算法已成为许多 Java 应用程序(包括 Eclipse)的默认设置。然而,它源自一个更古老的实现,该实现被各种归因于 Dan Bernstein 或 Chris Torek。那个较旧的算法最初在 Usenet 上流传,并且很难确定归属。比如有一些interesting commentary in this Apache code (搜索他们的名字)引用原始来源。

底线是,这是一个非常古老、简单的散列算法。它不是性能最好的,甚至在数学上也没有被证明是一个“好”的算法。但是简单,很多人用了很久,效果也不错,所以有很多历史支持。

关于objective-c - 覆盖 isEqual : and hash 的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/254281/

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