[英]Decoding/Encoding a struct with protocol type properties
我正在嘗試使用UserDefaults
保存配置數據結構,因此數據結構需要符合Codable
協議。 這是我的數據結構:
// Data structure which saves two objects, which conform to the Connection protocol
struct Configuration {
var from: Connection
var to: Connection
}
protocol Connection: Codable {
var path: String { get set }
}
// Two implementations of the Connection protocol
struct SFTPConnection: Connection, Codable {
var path: String
var user: String
var sshKey: String
}
struct FTPConnection: Connection, Codable {
var path: String
var user: String
var password: String
}
如果我只是將Codable
添加到Configuration
,它將不起作用。 所以我必須自己實現它。
extension Configuration: Codable {
enum CodingKeys: String, CodingKey {
case from, to
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
let from = try container.decode(Connection.self, forKey: .from)
let to = try container.decode(Connection.self, forKey: .to)
self.from = from
self.to = to
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(from, forKey: .from)
try container.encode(to, forKey: .to)
}
}
對於decode()
或encode()
每次調用,我都會收到錯誤Protocol type 'Connection' cannot conform to 'Decodable/Encodable' because only concrete types can conform to protocols
。
我可以看到編譯器很難識別,應該使用哪個類來解碼給定的對象。 但我認為對對象進行編碼應該很容易,因為Connection
類型的每個對象都實現了encode()
方法。
我知道,問題出在協議上,並且該協議不能與Decodable/Encodable
一起使用。 我將如何更改decode/encode
的代碼,以便我仍然可以將協議與各種實現一起使用? 我的猜測是以某種方式告訴decode/encode
要使用的協議實現。 我很感激這個問題的任何優雅的解決方案!
Swift 的一個限制是協議不能符合自身。 因此from
和to
不符合Codable
看起來很奇怪。
您可以通過使用泛型來繞過它,這基本上意味着您將from
和to
聲明為符合Codable
任意類型。 就是這樣:
struct Configuration<F: Connection, T: Connection>: Codable {
var from: F
var to: T
}
let myFrom = SFTPConnection(path: "foo", user: "me", sshKey: "hgfnjsfdjs")
let myTo = FTPConnection(path: "foo", user: "me", password: "hgfnjsfdjs")
let example = Configuration(from: myFrom, to: myTo)
所以F
和T
是符合Connection
類型。 當您在最后一行實例化example
時,編譯器推斷F
是SFTPConnection
而T
是FTPConnection
。
一旦我添加了通用參數, Configuration
就能夠在沒有擴展的情況下綜合符合Codable
。
要回答Sh_kahn的大約有兩個通用的參數來看,我這樣做是為了讓from
和to
是兩種不同類型的連接。 如果您總是希望兩個連接的類型相同,即總是兩個SFTPConnection
或兩個FTPConnection
您應該像這樣聲明Configuration
:
struct Configuration<C: Connection>: Codable {
var from: C
var to: C
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.