【问题标题】:Inheritance of Encodable Class可编码类的继承
【发布时间】:2018-06-22 14:53:27
【问题描述】:

我正在使用 Swift 4 和 Xcode 9.2 编写程序。我在编写可编码类(确切地说是类,而不是结构)时遇到了困难。当我试图从另一个类继承一个类时,JSONEncoder 不会从子类(子类)中获取所有属性。请看这个:

class BasicData: Encodable {

    let a: String
    let b: String

    init() {
        a = "a"
        b = "b"
    }
}

class AdditionalData: BasicData {

    let c: String

    init(c: String) {
        self.c = c
    }

}

let encode = AdditionalData(c: "c")

do {
    let data = try JSONEncoder().encode(encode)
    let string = String(data: data, encoding: .utf8)
    if let string = string {
        print(string)
    }
} catch {
}

它将打印:{"a":"a","b":"b"}

但我需要这个:{"a":"a","b":"b","c":"c"}

看起来 cAdditionalData 的属性只是不知何故丢失了。

所以问题是:如果我有使用协议 Encodable 签名的类,如何正确地制作子类(此类的子类,继承)类?

我会感谢任何帮助或建议。

【问题讨论】:

    标签: inheritance swift4 codable decodable encodable


    【解决方案1】:

    EncodableDecodable 涉及一些代码合成,其中编译器基本上为您编写代码。当您使BasicData 符合Encodable 时,这些方法将写入BasicData 类,因此它们不知道子类定义的任何附加属性。您必须在子类中覆盖 encode(to:) 方法:

    class AdditionalData: BasicData {
        let c: String
        let d: Int
    
        init(c: String, d: Int) {
            self.c = c
            self.d = d
        }
    
        private enum CodingKeys: String, CodingKey {
            case c, d
        }
    
        override func encode(to encoder: Encoder) throws {
            try super.encode(to: encoder)
            var container = encoder.container(keyedBy: CodingKeys.self)
            try container.encode(self.c, forKey: .c)
            try container.encode(self.d, forKey: .d)
        }
    }
    

    请参阅 this question 以了解与 Decodable 类似的问题。

    【讨论】:

    • 感谢您的帮助,它正在工作!我会将其标记为已接受。但是,如果不难的话,您能否编辑您的代码并将 Int 类型的属性 d 添加到 AdditionalData 类?看看如何对几个属性进行编码将会非常有趣。该怎么办?
    • 你的答案是完美的。过去两天我一直遇到一个问题,你的回答挽救了我的余生;)
    • 您好,我怎样才能使这部分可重复使用?任何想法 private enum CodingKeys: String, CodingKey { case c, d } override func encode(to encoder: Encoder) throws { try super.encode(to: encoder) var container = encoder.container(keyedBy: CodingKeys.self) try container .encode(self.c, forKey: .c) 试试 container.encode(self.d, forKey: .d) }
    【解决方案2】:

    在我的例子中,基类实际上不需要是 Codable。只有子类需要是可编码的。在这种情况下,不要将基类声明为 Codable,而只声明子类。通过这样做,您不需要执行任何这些 encode/codingKeys/init(from: Decoder) 样板文件。希望这对某些人有所帮助。

    【讨论】:

      猜你喜欢
      • 2020-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多