[英]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.