解码子类时忽略超类属性

Posted

技术标签:

【中文标题】解码子类时忽略超类属性【英文标题】:Ignoring superclass property while decoding subclass 【发布时间】:2017-10-17 00:10:34 【问题描述】:

我正在尝试创建继承的数据模型,以便使用 JSONDecoder 解析它。

class FirstClass : Codable 
    let firstClassProperty: Int
    final let arrayOfInts: [Int]


class SecondClass : FirstClass 
    let secondClassProperty1: Int
    let secondClassProperty2: Int

    private enum CodingKeys : String, CodingKey 
        case secondClassProperty1, secondClassProperty2
    

    required init(from decoder: Decoder) throws 
        let container = try decoder.container(keyedBy: CodingKeys.self)

        secondClassProperty1 = try container.decode(Int.self, forKey: .secondClassProperty1)
        secondClassProperty2 = try container.decode(Int.self, forKey: .secondClassProperty2)

        try super.init(from: decoder)
    

我将此 JSON 用于FirstClass


    "firstClassProperty":  123,
    "arrayOfInts": [
        123
    ]

这是SecondClass


  "firstClassProperty": ,
  "secondClassProperty1": ,
  "secondClassProperty2": 

如果在这种情况下关键字 final 不起作用,我如何才能摆脱子类中的 arrayOfInts 而让它出现在超类中?

这里是Playground。感谢您的回答!

【问题讨论】:

如果不是总是需要arrayOfInts,为什么它会出现在你的基类中? 这里似乎不需要层次结构。 【参考方案1】:

一个快速的技巧是将其声明为可选。例如:

class FirstClas: Codable 
    let firstClassProperty: Int
    final let arrayOfInts: [Int]?

这将自动解决缺少的arrayOfInts

手动解决方案。另一种解决方案是自己实现Decodable 协议——就像你在SecondClass 中所做的那样——并使用decodeIfPresent 解码arrayOfInts(否则使用默认值)。


超类解码。顺便说一句,将Decoder 转发给超类的推荐方法是使用superDecoder() 方法:

...
let superDecoder = try container.superDecoder()
try super.init(from: superDecoder)

【讨论】:

@LeoDabus 我自己是struct junkie,但是,如果没有来自good solitude3的更多信息,我不能像你说的那样直接杀死他的课程,哈哈;)他可能需要这种能力一个更大的应用程序,具有一整套未知的设计约束...... @LeoDabus 不是真的。正如我在回答中使用的那样,一个特定的superDecoder() API 向我表明,Apple 明确地将其设计为供 classes 使用。这里和那里可能有一些缺失的部分,但我的意图似乎很清楚...... @LeoDabus ...苹果实际上提供了complete, detailed example in WWDC 2017 :-) 我不会这么说的。这个问题主要集中在忽略超类属性(而不是关于继承作为另一个问题的全面讨论)。 OP 真的无法通过仅查看另一个更大的问题来破解解决方案,恕我直言......【参考方案2】:

你可以这样使用:

class FirstClass : Codable 
    let firstClassProperty: Int
    final let arrayOfInts: [Int]?
    required init(from decoder: Decoder) throws 
        let container = try decoder.container(keyedBy: CodingKeys.self)
        firstClassProperty = try container.decode(Int.self, forKey: .firstClassProperty)
        arrayOfInts = try container.decodeIfPresent([Int].self, forKey: .arrayOfInts)
    

【讨论】:

如果属性已经被标记为可选,我认为自动生成的代码在这里可能就足够了——顺便说一下,应该和你手动生成的非常相似写;)

以上是关于解码子类时忽略超类属性的主要内容,如果未能解决你的问题,请参考以下文章

如何用子类内部状态包装所有 python 超类方法?

Hibernate 错误地在子类而不是超类中寻找属性的设置器?

OWL:如何从超类继承两个类之间的属性关系?

JavaScript类继承

Java 只返回超类的属性

Java入门