Swift:具有相同属性的不同对象:哈希值

Swift:具有相同属性的不同对象:哈希值,swift,hash,Swift,Hash,目前我有一个泛型类型的类,我想通过 contains() 方法,使类符合哈希协议,并为每个对象提供哈希值。现在我的问题是,我的对象具有完全相同的属性,而数组似乎无法真正区分它们我当前的方法是使用属性的散列值之一作为类的散列值 == <T> (lhs: ClassA<T>, rhs: ClassA<T>) -> Bool == <T> (lhs: ClassA<T>, rhs: ClassA<T>) -> Bo

目前我有一个泛型类型的类,我想通过

contains()
方法,使类符合哈希协议,并为每个对象提供哈希值。现在我的问题是,我的对象具有完全相同的属性,而数组似乎无法真正区分它们我当前的方法是使用属性的散列值之一作为类的散列值

== <T> (lhs: ClassA<T>, rhs: ClassA<T>) -> Bool
== <T> (lhs: ClassA<T>, rhs: ClassA<T>) -> Bool
函数是通过比较哈希值来完成的。我尝试使用像id这样的静态属性,但对于泛型类型,不支持静态属性

我应该如何定义散列值,以便仍然可以区分具有相同属性的不同对象


编辑:我让它直接符合Hashable,因为它在程序的其他部分也用作dict中的键,因为Hashable已经符合Equatable。

刚刚意识到,有一种简单的方法可以在

contains()
方法:使用

return lhs === rhs
在==函数中,直接比较对象。它现在是这样工作的

我当前的方法是使用属性的散列值之一作为 类的哈希值,以及

== <T> (lhs: ClassA<T>, rhs: ClassA<T>) -> Bool
== <T> (lhs: ClassA<T>, rhs: ClassA<T>) -> Bool
现在,您可以将Sequence的方法与==重载结合使用,以检查给定实例是否在数组中:

var array = [ClassA("foo")] // assuming ClassA has an init(_: T) and a suitable ==
                            // implementation to compare that value

let someInstanceToFind = ClassA("foo")
print(array.contains { $0 == someInstanceToFind }) // true
如果您想让ClassA有一个hashValue,那么只需编写一个扩展,在T可散列时定义一个hashValue:

不幸的是,这确实意味着ClassA在t显式符合Hashable时不会显式符合,但它将有一个hashValue和==实现。如果满足给定的where子句,将通过允许显式符合协议来改变这一点,但这尚未实现

如果您需要显式符合Hashable,例如在集合中使用类的实例或作为字典键,那么一个解决方案是创建包装器类型:

struct HashableClassA<T : Hashable> : Hashable {

    var base: ClassA<T>

    init(_ base: ClassA<T>) {
        self.base = base
    }

    static func ==(lhs: HashableClassA, rhs: HashableClassA) -> Bool {
        return lhs.base == rhs.base
    }

    var hashValue: Int {
        return base.hashValue
    }
}

现在,在添加到集合或字典之前,只需将ClassA实例包装在HashableClassA实例中。

如果希望两个具有相同属性的不同对象不相等,您可以为新对象添加标识符(例如,自动递增id)来区分它们,或者只使用它们的指针值来表示类类型。请注意,这可能会导致两个不同实例出现令人惊讶的结果,这两个实例看起来应该是等效的,但不是因为它们不是同一个实例。