Swift-我可以使协议可哈希化吗?

问题描述

我写了一个简单的协议Data

public protocol Data {
    var state: [String: Any] { get set }    
    var objectId: String? { get set }    
}

public extension Data {
    var objectId: String? {
        get {
            return self.state["objectId"] as? String
        }
        set {
            self.state["objectId"] = newValue
        }
    }
}

这样,我创建了几种符合它的类型:

public struct Person: Data {
    public var state: [String : Any]
}
public struct Car: Data {
    public var state: [String : Any]
}
// ...

现在我要做的是使每种类型都Hashable,问题是我需要在每种类型中编写以下代码

extension Car Hashable {
    public static func == (lhs: Car,rhs: Car) -> Bool {
        return lhs.objectId == rhs.objectId
    }        
    public func hash(into hasher: inout Hasher) {
        hasher.combine(self.objectId ?? "")
    }    
}
// ...

我想知道的是,是否有可能将Data的{​​{1}}声明为Hashable。当我使用协议时,找不到任何方法

谢谢您的帮助。

解决方法

正如@Leo Dabus在他的评论中提到的,由于本机Foundation.Data类型的存在,您可能应该为协议使用另一个名称。

无论哪种方式,都可以使用以下代码在您的Hashable协议中实现Data协议:

public protocol Data: Hashable {
    var state: [String: Any] { get set }
    var objectId: String? { get set }
}

public extension Data {
    var objectId: String? {
        get {
            return self.state["objectId"] as? String
        }
        set {
            self.state["objectId"] = newValue
        }
    }
    
    static func == (lhs: Self,rhs: Self) -> Bool {
        return lhs.objectId == rhs.objectId
    }
    
    func hash(into hasher: inout Hasher) {
        hasher.combine(self.objectId ?? "")
    }
}

尽管这会带来副作用,因为协议Data具有自身或相关类型要求,因此只能用作通用约束:

enter image description here

这意味着您现在可以像这样使用Data协议:

func myFunc<T: Data>(data: T) {
    
}