I have a class which provides a ThreadsafeDictionary
public class ThreadsafeDict<Key:Hashable,Value>{
private var dict:[Key:Value]
private let queue:DispatchQueue
public init(_ newDict:[Key:Value]) {
dict = newDict
queue = DispatchQueue(label: "com.hobbyistsoftware.threadsafe.dict",
qos: DispatchQoS.userInitiated,
attributes: .concurrent)
}
//Snip
}
it's seems like it would be easy to make this decodable if the key/value allow
(just encoding/decoding to the 'raw' dictionary)
extension ThreadsafeDict:Decodable where Key:Decodable,Value:Decodable {
required public init(from decoder: Decoder) throws {
let dict = try Dictionary<Key,Value>.init(from: decoder)
self.init(dict)
}
}
however this hits a couple of errors:
Designated initializer cannot be declared in an extension of 'ThreadsafeDict'; did you mean this to be a convenience initializer?
Initializer requirement 'init(from:)' can only be satisfied by a 'required' initializer in the definition of non-final class 'ThreadsafeDict<Key, Value>'
Of course - I can't provide the initialiser within the class because Key & Value are not necessarily Decodable
Am I missing something?
Jumhyn
(Frederick Kellison-Linn)
2
You have a couple options here. You could define the init(from:) in the body of the class with the where clause attached to the declaration itself:
required public init(from decoder: Decoder) throws
where Key: Decodable, Value: Decodable
{
dict = try Dictionary<Key,Value>.init(from: decoder)
queue = DispatchQueue(label: "com.hobbyistsoftware.threadsafe.dict",
qos: DispatchQoS.userInitiated,
attributes: .concurrent)
}
extension ThreadsafeDict:Decodable where Key: Decodable, Value: Decodable {}
Also, if you don't need clients to be able to inherit from ThreadsafeDict (which I'm guessing you don't since it is public and not open?), you can just make it final and use the convenience init:
public class ThreadsafeDict<Key: Hashable, Value> { ... }
extension ThreadsafeDict:Decodable where Key: Decodable, Value: Decodable {
convenience public init(from decoder: Decoder) throws {
let dict = try Dictionary<Key,Value>.init(from: decoder)
self.init(dict)
}
}
2 Likes
I had no idea you could put a where in a function definition!
I have only ever seen them in extension declarations.
Thank you - that's perfect.
1 Like