您可以“扩展"(即添加额外的初始化逻辑)为 Codable 对象自动生成的构造函数吗? [英] Can you “extend” (i.e. add additional initialization logic to) the auto-generated constructor for a Codable object?

查看:35
本文介绍了您可以“扩展"(即添加额外的初始化逻辑)为 Codable 对象自动生成的构造函数吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当您在对象上实现 Codable 时,编译器可以自动为您生成构造函数.但是,只有当您自己没有编写接受解码器的初始化程序时,它才会这样做.

When you implement Codable on an object, the compiler can automatically generate a constructor for you. However it only does this if you haven't written an initializer that accepts a decoder yourself.

也就是说,我们有一个对象有大约 50 个 let 属性,这些属性是从解码器设置的,但我们还有五个基于这些 let 属性的计算属性.

That said, we have an object with ~50 let properties which are set from the decoder, but we also have five computed properties which are based on those let properties.

从技术上讲,如果我们可以在初始化程序中计算它们,在解码器设置其他 50 个之后,我们可以简单地将结果存储在它们自己的 let 变量中,完全不需要计算属性.

Technically if we could compute them in the initializer, after the decoder has set the other 50, we could simply store the results in let vars of their own, eliminating the need for computed properties altogether.

问题是,如前所述,如果您实现自己的初始化程序,编译器不会为您自动生成一个,因此您不仅要初始化计算"值,而且要全部 值.

The problem is, as mentioned, if you implement your own initializer, the compiler doesn't auto-generate one for you so you're left not just initializing your 'computed' values, but all values.

那么有没有一种方法可以将自己插入到初始化/解码过程中,而不必自己完全重写初始化程序?

So is there a way you can insert yourself as part of the initialization/decoding process without having to fully rewrite the initializer yourself?

推荐答案

您正在寻找的类似于委托模式,其中解码器通知其委托已完成解码.遗憾的是,它还没有添加到 Swift 中.我能想到的最接近的是使用继承,以便 Swift 可以为基类中的 50 个 let 自动生成解码器,并且您可以在子类中初始化您的计算属性.例如:

What you are looking for is similar to the delegate pattern where the decoder informs its delegate that it has finished decoding. Sadly, it's not yet added to Swift. The closest I can think off is to use inheritance so Swift can auto generate the decoder for the those 50 let in the base class, and you can initialize your computed properties in a subclass. For example:

class A: Decodable {
    let firstName: String
    let lastName: String
}

class B: A {
    private var _fullName: String! = nil
    var fullName: String { return _fullName }

    required init(from decoder: Decoder) throws {
        try super.init(from: decoder)
        _fullName = firstName + " " + lastName
    }
}

在 A 类中定义 50 个属性,并将所有计算属性留在 B 类中.

Define your 50 properties in class A and leave all the computed properties in class B.

或者根据您的建议,您也可以使用lazy var:

Or at your suggestion, you can also use lazy var:

struct Model: Decodable {
    let firstName: String
    let lastName: String

    // private(set) so users cannot change value of the
    // pre-computed property
    lazy private(set) var fullName = self.firstName + " " + self.lastName
}

// But you can't use a let here, since calling fullName
// for the first time will mutate the struct
var model = try JSONDecoder().decode(Model.self, from: json)

这篇关于您可以“扩展"(即添加额外的初始化逻辑)为 Codable 对象自动生成的构造函数吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆