[英]Swift: Decode arbitrary protocol types
我正在嘗試解碼具有符合協議的可變屬性的JSON。
考慮以下結構集:
protocol P: Decodable {
var id: String { get }
}
struct A: P {
let id: String
var someThing: Double
}
struct B: P {
let id: String
var anotherThing: String
}
struct S: Decodable {
let id: String
let instanceOfProtocol: P
}
我們正在嘗試解碼S
Decodable
的自動綜合無法正常工作(因為解碼器無法知道P
將被解碼為哪種類型),所以我嘗試在自定義初始化程序中執行以下操作:
if let instance = try? container.decode(A.self, forKey: .instanceOfProtocol) {
instanceOfProtocol = instance
} else if let instance = try? container.decode(B.self, forKey: .instanceOfProtocol) {
instanceOfProtocol = instance
} else {
throw NoConformingTypeError()
}
這可行,但是非常冗長,重復,並且伸縮性不佳,因此我正在尋找其他選擇。
superDecoder
: let possibleTypes: [P.Type] = [A.self, B.self]
let childDecoder = try container.superDecoder(forKey: .instanceOfProtocol)
let decoded: [P] = possibleTypes.compactMap { try? $0.init(from: childDecoder) }
guard let instance = decoded.first else { throw NoConformingTypeError() }
instanceOfProtocol = instance
這也可以正常工作,但是我不確定superDecoder
是否打算以這種方式使用,或者將來是否會崩潰。
let possibleTypes: [P.Type] = [A.self, B.self]
let decoded: [P] = possibleTypes.compactMap { try? container.decode($0, forKey: .instanceOfProtocol) }
guard let instance = decoded.first else { throw NoConformingTypeError() }
instanceOfProtocol = instance
到目前為止,這似乎是最好的選擇,但由於Ambiguous reference to member 'decode(_:forKey:)'
不Ambiguous reference to member 'decode(_:forKey:)'
,因此無法編譯。
編輯:
struct S<T: P>: Decodable {
let id: String
let instanceOfProtocol: T
}
這真是太好了,因為“ Decodable
合成再次起作用了!
但是,現在我們必須知道類型T
,因為解碼站點現在需要一種類型:
try JSONDecoder().decode(S<A>.self, from: data)
try JSONDecoder().decode(S<B>.self, from: data)
在我們的用例中,我們不知道類型是什么,因此我們必須再次檢查這里...
使用通用類型:
struct S<T: P>: Decodable {
let id: String
let instanceOfProtocol: T
}
記住Protocol
不是Type
! Swift是強類型語言。 因此,即使對象的調用者無法暴露實際的類型,它也必須首先知道所有對象的類型。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.