我无法在子类中设置b属性。 它是继承自Codable的父类,并且似乎运行良好。
我觉得我错过了一些非常明显的东西,但是我很难看到木头的树木。
下面是我的问题的游乐场示例。 b保持为0,尽管设置为10 。 它是传入的子类,但是可以设置的父属性(非常奇怪!)。
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将非常感激地收到任何提示或指示。
试过Xcode 9.3,Swift 4.1I 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.
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)The output from this is:
a >> 5 b >> 0Any tips or pointers would be gratefully received.
tried in Xcode 9.3, Swift 4.1最满意答案
Codable的魔力依赖于简单性(使用不支持继承的结构)。
定制越多,代码越多
你必须在子类中编写一个自定义初始值设定项来考虑继承(感谢Hamish注意CodingKeys和初始化程序是在基类中合成的),我故意省略了Encodable部分
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) }The magic of Codable relies on simplicity (using structs which don't support inheritance).
The more custom, the more code
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) }更多推荐
发布评论