使用“编码"设置属性值不能通过继承工作 [英] Using "Codable" to set property values doesn't work through inheritance

查看:67
本文介绍了使用“编码"设置属性值不能通过继承工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法在子类中设置 b 属性.它是从 Codable 继承的父类,并且似乎运行良好.

I am unable to set the b property in a child class. It is the parent class that inherits from Codable, and that seems to be working well.

我觉得我确实缺少一些明显的东西,但是我很难看到树木所用的木头.

I feel like I am missing something really obvious, but I am having trouble seeing the wood for the trees.

下面是我的问题的一个操场例子.尽管设置为 10 b 仍为0.传入的是子类,但是可以设置父属性(很奇怪!).

Below is a playground example of my problem. b remains 0, despite being set to 10. It is the child class that gets passed in, but the parent property that can be set (very weird!).

class Primary : Codable {
    var a: Int = 0
}

class Secondary : Primary {
    var b: Int = 0
}

let c = Secondary.self

func testRef<T: Codable>(_ t: T.Type) {
    let json = "{\"a\":5, \"b\" : 10}".data(using: .ascii)!
    let testCodable = try? JSONDecoder().decode(t.self, from: json)
    print("a >> \((testCodable as! Primary).a)")
    print("b >> \((testCodable as! Secondary).b)")
}

testRef(c)

输出为:

a >> 5
b >> 0

任何提示或指示都将不胜感激.

Any tips or pointers would be gratefully received.

  • 在Xcode 9.3,Swift 4.1中尝试

推荐答案

Codable 的魔力在于简单性(使用不支持继承的结构).

The magic of Codable relies on simplicity (using structs which don't support inheritance).

自定义程度越高,代码越多

您必须在子类中编写一个自定义的初始化程序以考虑继承(感谢Hamish,注意CodingKeys和初始化程序是在基类中合成的),我省略了 Encodable 故意

You have to write a custom initializer in the subclass to consider inheritance (thanks to Hamish for the note that CodingKeys and initializer are synthesized in the base class), I omitted the Encodable part intentionally

class Primary : Decodable {
    var a: Int

/*
   private enum CodingKeys: String, CodingKey { case a }

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        a = try container.decode(Int.self, forKey: .a)
    }
*/
}

class Secondary : Primary {
    var b: Int

    private enum CodingKeys: String, CodingKey { case b }

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        b = try container.decode(Int.self, forKey: .b)
        try super.init(from: decoder)
    }
}


func testRef<T: Decodable>() throws -> T {
    let json = "{\"a\":5, \"b\" : 10}".data(using: .utf8)!
    return try JSONDecoder().decode(T.self, from: json)
}

do {
    let secondary : Secondary = try testRef()
    print(secondary.a, secondary.b) // 5 10
} catch { print(error) }

这篇关于使用“编码"设置属性值不能通过继承工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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