objective-c - 覆盖 NSArray 的哈希值

标签 objective-c

SO answer显示 NSDictionary 的哈希是字典中的条目数。 ( Similarly, the hash of an NSArray is its length 。)答案继续建议创建一个类别以提供更好的哈希实现。

If you need to have a more accurate hash value, you can provide one yourself in an Obj-C category.

但是当我尝试这样做时,它似乎仍然使用原始哈希实现。

我们在 NSDictionary+Hash.h 中有 header

#import <Foundation/Foundation.h>

@interface NSDictionary (Hash)
- (NSUInteger)hash;
@end

以及NSDictionary+Hash.m中的实现:

#import "NSDictionary+Hash.h"

@implementation NSDictionary (Hash)

- (NSUInteger)hash
{
    // Based upon standard hash algorithm ~ https://stackoverflow.com/a/4393493/337735
    NSUInteger result = 1;
    NSUInteger prime = 31;
    // Fast enumeration has an unstable ordering, so explicitly sort the keys
    // https://stackoverflow.com/a/8529761/337735
    for (id key in [[self allKeys] sortedArrayUsingSelector:@selector(compare:)]) {
        id value = [self objectForKey:key];
        // okay, so copying Java's hashCode a bit:
        // http://docs.oracle.com/javase/6/docs/api/java/util/Map.Entry.html#hashCode()
        result = prime * result + ([key hash] ^ [value hash]);
    }
    return result;
}

一个简单的单元测试显示原始实现正在使用中:

#import "NSDictionary+Hash.h"

#import <SenTestingKit/SenTestingKit.h>

@interface NSDictionary_HashTest : SenTestCase
@end

@implementation NSDictionary_HashTest

- (void)testHash
{
    NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
                          @"val1", @"key1", @"val2", @"key2", nil];
    NSUInteger result = 1;
    result = 31 * result + ([@"key1" hash] ^ [@"val1" hash]);
    result = 31 * result + ([@"key2" hash] ^ [@"val2" hash]);
    STAssertEquals([dict hash], result, nil);
}

@end

此测试失败,显示“‘2’应等于‘2949297985’”。

现在,如果我在类别 header 和实现文件中将方法从 hash 重命名为 hashy(例如),则 [dict hashy] 会返回正确的值。无法覆盖类别中的“内置”方法吗?我做错了什么吗?

最佳答案

NSDictionary 是一个类簇——当您向 NSDictionary 发送消息时,您与之交互的永远不是 NSDictionary 的实际实例,而是私有(private)子类的实例。所以当你重写类别中的 hash 方法时,它确实重写了 NSDictionary 中的那个方法,但是具体的子类有它自己的 hash 方法,所以它重写了你的方法。

如果您真的想这样做,我认为您需要检查类 NSDictionaryI 和 NSDictionaryM 是否存在并动态覆盖它们的 hash 方法。但这在内部实现细节上是乱七八糟的,我不建议这样做,除非你在某种程度上真的陷入了困境。如果您分析并发现 NSDictionary 的 hash 方法有问题,我会尝试创建一个包装 NSDictionary 但提供其自己的自定义 hash 方法的类,然后再处理私有(private)实现类 — 实现类可以在没有警告的情况下更改(并且之前已经更改),因此任何依赖它们的设计都是脆弱的。

关于objective-c - 覆盖 NSArray 的哈希值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14696922/

相关文章:

ios - UITableView如何操作队列并发下载

ios - 为 UITableViewCell 添加不同的子层覆盖 Cell 的 subview

objective-c - 访问属性方法和类字段之间的区别(Objective-C)

ios - Plist 从 URL 到 NSMutableArray

objective-c - 操作两个数组

iphone - If 语句不适用于空格字符

objective-c - cocoa Pod svn 问题

objective-c - iOS dispatch_async,在 iOS 4 上崩溃

iphone - NSPredicate - 评估两个条件

iOS 从通知中删除观察者 : Can I call this once for all observers? 即使没有?