【问题标题】:Extend existing (generic) swift class to be hashable将现有(通用)swift 类扩展为可散列
【发布时间】:2015-10-17 16:40:19
【问题描述】:

我有一些类要放入字典中,但是该类不符合 Hashable,我不能将其用作 Swift 字典中的键。由于它是一个类,它可以通过它在内存中的位置来识别,并且我很乐意使用它的标识符,所以类型本身无论如何都不属于值语义世界。

因此我声明了一个扩展来实现它

extension SomeGenericType : Hashable {

    public var hashValue: Int {
        return unsafeAddressOf(self).hashValue
    }

}

这似乎没问题,但是 Hashable 从 Equatable 继承,所以我也需要实现 tha,我的第一次尝试:

public func ==(lhs: SomeGenericType, rhs: SomeGenericType) -> Bool {
    return unsafeAddressOf(lhs) == unsafeAddressOf(rhs)
}

错误

 "Reference to generic type 'SomeGenericType' requires arguments in <...>"

...足够公平,让我们这样做

public func ==<T : SomeGenericType >(lhs: T, rhs: T) -> Bool {
    return unsafeAddressOf(lhs) == unsafeAddressOf(rhs)
}

现在它说

 "Reference to generic type 'SomeGenericType' requires arguments in <...>" 

嗯,所以我可以使所有 SomeGenericType 都可以使用它,而不管它得到什么类型。也许我们可以把 AnyObject 放在那里?

public func ==<T : SomeGenericType<AnyObject>>(lhs: T, rhs: T) -> Bool {
    return unsafeAddressOf(lhs) == unsafeAddressOf(rhs)
}

好的,现在 == 很高兴,但显然我没有正确实现 Hashable,因为我的 Hashable 扩展现在有一个错误说:

"Type 'SomeGenericType<T>' does not conform to protocol 'Equatable'"

我尝试在 SomeGenericType 上摆弄一个受限扩展,但我似乎无法让一个类型的受限扩展采用另一种协议,语言语法似乎不允许它,所以我在这里有点麻烦

编辑,供参考 SomeGenericType 定义如下:

class SomeGenericType<T> {

}

【问题讨论】:

  • 我已经编辑以展示 SomeGenericType 是如何实现的,当我扩展的类型不是通用时,原始版本可以工作

标签: swift generics


【解决方案1】:

正确的语法是

public func ==<T>(lhs: SomeGenericType<T>, rhs: SomeGenericType<T>) -> Bool {
    return unsafeAddressOf(lhs) == unsafeAddressOf(rhs)
}

操作数必须是 SomeGenericType 的实例 相同类型占位符T

对于 Swift 3, 使用 ObjectIdentifier 而不是 unsafeAddressOf

【讨论】:

【解决方案2】:

这是一个较老的问题,但我最近遇到了类似的问题,除了我有一个struct

您可能想要实现 4 个不同的中缀运算符函数:

// #1
public func ==<T>(lhs: SomeGenericType<T>, rhs: SomeGenericType<T>) -> Bool {
    return lhs === rhs // it's a class right - check the reference
}

// #2
public func !=<T>(lhs: SomeGenericType<T>, rhs: SomeGenericType<T>) -> Bool {
    return !(lhs === rhs)
}

// #3
public func ==<T, U>(lhs: SomeGenericType<T>, rhs: SomeGenericType<U>) -> Bool {
    return lhs.hashValue == rhs.hashValue
}

// #4
public func !=<T, U>(lhs: SomeGenericType<T>, rhs: SomeGenericType<U>) -> Bool {
    return lhs.hashValue != rhs.hashValue
}

问题解决了吗?程序应该使用这些而不是标准库中的通用函数。

您也可以通过hashValue 查看所有内容。 ;)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-07
    • 2021-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-18
    相关资源
    最近更新 更多