将现有(通用)swift类扩展为可清除

时间:2015-10-17 16:40:20

标签: swift generics

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

因此,我声明了一个扩展,使其成为

extension SomeGenericType : Hashable {

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

}

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

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,因为我的可扩展扩展程序现在出现错误:

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

我试过摆弄SomeGenericType上的约束扩展,但我似乎无法使一个类型的约束扩展采用另一种协议,语言语法似乎不允许它,所以我在这里有点腌渍

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

class SomeGenericType<T> {

}

2 个答案:

答案 0 :(得分:4)

正确的语法是

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

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

对于 Swift 3,使用ObjectIdentifier代替unsafeAddressOf

答案 1 :(得分:0)

这是一个较旧的问题,但我最近遇到了类似的问题,除了我有一个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
}

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

您还可以通过hashValue检查所有内容。 ;)