Reputation: 1452
I have written a simple protocol 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
}
}
}
This way, I have created several types conforming to it:
public struct Person: Data {
public var state: [String : Any]
}
public struct Car: Data {
public var state: [String : Any]
}
// ...
Now what I want to do is to make each of these types Hashable
, the problem is that I need to write this code in every type:
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 ?? "")
}
}
// ...
What I want to know is if it is possible to generically declare Data
as Hashable
from its objectId
. As I am using a protocol, I couldn't find a way to do so.
Thank you for your help.
Upvotes: 2
Views: 2989
Reputation: 8327
As @Leo Dabus mentioned in his comment, you should probably use another name for your protocol due to native Foundation.Data
type existence.
Either way, using the following code you can implement Hashable
protocol into your Data
protocol:
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 ?? "")
}
}
Although this will have as a side effect that protocol Data
can only be used as a generic constraint because it has Self or associated type requirements:
Meaning that you can now on use the Data
protocol like this:
func myFunc<T: Data>(data: T) {
}
Upvotes: 4