首页 > 解决方案 > 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 ?? "")
    }    
}
// ...

我想知道的是是否可以DataHashable它的objectId. 当我使用协议时,我找不到这样做的方法。

谢谢您的帮助。

标签: swiftprotocolshashable

解决方案


正如@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只能用作通用约束,因为它具有 Self 或关联的类型要求:

在此处输入图像描述

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

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

推荐阅读