superEncoder
英寸编码器和superDecoder
英寸解码器是一种能够"保留"容器内部嵌套容器的方法,而不需要提前知道它将是什么类型.
这样做的主要目的之一是支持Encodable
/Decodable
类中的继承:类T: Encodable
可以 Select 将其内容编码为UnkeyedContainer
,但其子类U: T
可以 Select 将其内容编码为KeyedContainer
.
在U.encode(to:)
中,U
需要调用super.encode(to:)
,并传入一个Encoder
,但它不能传入它接收到的Encoder
,因为它已经用密钥方式对其内容进行了编码,而T
从Encoder
请求一个未加密的容器是无效的.(一般来说,U
甚至不知道T
想要什么样的容器.)
然后,逃生舱是U
向其容器请求嵌套的101,以便能够将其传递给其超类.容器将为嵌套值留出空间,并创建一个新的Encoder
,允许写入该保留空间.T
然后可以使用嵌套的Encoder
进行编码.
结果看起来好像U
请求了一个嵌套容器,并将T
的值编码到其中.
为了使这一点更具体,请考虑以下内容:
import Foundation
class T: Encodable {
let x, y: Int
init(x: Int, y: Int) { self.x = x; self.y = y }
func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
try container.encode(x)
try container.encode(y)
}
}
class U: T {
let z: Int
init(x: Int, y: Int, z: Int) { self.z = z; super.init(x: x, y: y) }
enum CodingKeys: CodingKey { case z }
override func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(z, forKey: .z)
/* How to encode T.x and T.y? */
}
}
let u = U(x: 1, y: 2, z: 3)
let data = try JSONEncoder().encode(u)
print(String(data: data, encoding: .utf8))
U
有几个选项可以 Select 如何对x
和y
进行编码:
它可以在CodingKeys
枚举中包含x
和y
,并直接对它们进行编码,从而真正覆盖T
的编码策略.这忽略了T
希望编码的方式,如果需要decoding,则意味着您必须能够创建一个调用其init(from:)
的新T
without
它可以调用super.encode(to: encoder)
将超类编码到same编码器中.在这种情况下,这将是crash,因为U
已经从encoder
请求密钥容器,而调用T.encode(to:)
将立即从同一编码器请求未密钥容器
- 一般来说,如果
T
和U
都请求相同的容器类型,那么may就可以工作,但不建议依赖它.根据T
的编码方式,它可能会覆盖U
已经编码的值
用super.encode(to: container.superEncoder())
嵌套T
inside个键控容器;这将在容器字典中保留一个位置,创建一个新的Encoder
,并对该编码器进行T
次写入.在JSON中,这样做的结果将是:
{ "z": 3,
"super": [1, 2] }