【问题标题】:Can you “extend” (i.e. add additional initialization logic to) the auto-generated constructor for a Codable object?你可以为 Codable 对象“扩展”(即添加额外的初始化逻辑)自动生成的构造函数吗?
【发布时间】:2018-08-25 20:29:42
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: initialization swift4 initializer codable


    【解决方案1】:

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

    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 类中。


    或者根据您的建议,您也可以使用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)
    

    【讨论】:

    • 我什至没有想到这种方法!很酷,虽然您不是也必须使 V 类可解码吗?
    • 另外,我实际上完全忘记了 Swift 的 lazy var 功能,它还允许您只计算一次值,这是我的主要目标。由于该站点旨在帮助他人,因此如果您将有关 lazy var 的部分添加为替代项,以便您的答案显示两者,我会将其标记为已接受。 :)
    猜你喜欢
    • 2021-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-13
    • 1970-01-01
    • 2015-01-03
    • 2012-03-05
    相关资源
    最近更新 更多