我正兜圈子试图得到Hashable
与多个人一起工作struct
符合相同的protocol
.
我有一个协议SomeLocation
声明如下:
protocol SomeLocation {
var name:String { get }
var coordinates:Coordinate { get }
}
然后我创建多个包含类似数据的对象,如下所示:
struct ShopLocation: SomeLocation, Decodable {
var name: String
var coordinates: Coordinate
init(from decoder: Decoder) throws {
...
}
}
struct CarLocation: SomeLocation, Decodable {
var name: String
var coordinates: Coordinate
init(from decoder: Decoder) throws {
...
}
}
我稍后可以通过声明在同一个数组中使用它们:
let locations: [SomeLocation]
问题是,我创建了一个MKAnnotation
子类并且需要使用自定义Hashable
on the SomeLocation
对象。
final class LocationAnnotation:NSObject, MKAnnotation {
let location:SomeLocation
init(location:SomeLocation) {
self.location = location
super.init()
}
}
override var hash: Int {
return location.hashValue
}
override func isEqual(_ object: Any?) -> Bool {
if let annot = object as? LocationAnnotation
{
let isEqual = (annot.location == location)
return isEqual
}
return false
}
这给了我两个错误:
“SomeLocation”类型的值没有成员“hashValue”二元运算符
“==”不能应用于两个“SomeLocation”操作数
所以我添加了Hashable
我的协议SomeLocation
协议:
protocol SomeLocation: Hashable {
...
}
这消除了 hashValue 不可用的第一个错误,但现在我在声明的地方收到错误let location:SomeLocation
saying
协议“SomeLocation”只能用作通用约束,因为它具有 Self 或关联的类型要求
所以看起来我不能添加Hashable
到协议。
我可以添加Hashable
直接到实现的每个结构体SomeLocation
协议,但这意味着我需要使用这样的代码,并在每次我可能创建另一个符合协议的对象时不断更新它SomeLocation
协议。
override var hash: Int {
if let location = location as? ShopLocation
{
return location.hashValue
}
return self.hashValue
}
我尝试过另一种方法,通过制作SomeLocationRepresentable
struct:
struct SomeLocationRepresentable {
private let wrapped: SomeLocation
init<T:SomeLocation>(with:T) {
wrapped = with
}
}
extension SomeLocationRepresentable: SomeLocation, Hashable {
var name: String {
wrapped.name
}
var coordinates: Coordinate {
wrapped.coordinates
}
func hash(into hasher: inout Hasher) {
hasher.combine(name)
hasher.combine(coordinates)
}
static func == (lhs: Self, rhs: Self) -> Bool {
return lhs.name == rhs.name && lhs.coordinates == rhs.coordinates
}
}
但是当我尝试在中使用它时LocationAnnotation
类如
let location: SomeLocationRepresentable
init(location:SomeLocation) {
self.location = SomeLocationRepresentable(with: location)
super.init()
}
我收到一个错误
协议类型“SomeLocation”的值不能符合“SomeLocation”;只有 struct/enum/class 类型可以符合协议
有可能实现我想做的事情吗?使用全部符合协议的对象并使用自定义Hashable
将一个与另一个进行比较?