从json初始化子类

时间:2017-05-19 09:13:55

标签: json swift inheritance swift-protocols

我正在寻找一种坚持任意子类的好方法。

我在保存时编写对象asDictionary to json,在加载时编写init(json) them back。结构为Group,其Unit种类不同。 Group仅将其单位视为实施UnitProtocol的内容。

Groups and Units

UA的子类Unit等与单元具有完全相同的数据。因此数据方面,asDictionaryinit(json)非常适合Unit。子类仅在逻辑上有所不同。所以当从文件中恢复它们时,我相信它必须是初始化的确切子类。

(差)我想到的解决方案

  1. 让每个小组都知道它可以包含不同子类的单位,而不仅仅是[UnitProtocol],而是[UA][UB]等,可以单独保存,恢复按其各自的子内容,并在初始化时合并为[UnitProtocol]
  2. 使用其类名存储子单元并创建一个Unit.Init(json),以某种方式能够根据子类型传递初始化。
  3. ?仍在思考,但我相信在不违反单一责任政策的情况下,我可以在这里学习以可维护的方式做到这一点。

2 个答案:

答案 0 :(得分:1)

对于json的init类,我使用了这个技术:

        //For row in json
        for row in json {
            //namespace it use for init class
            let namespace = (Bundle.main.infoDictionary!["CFBundleExecutable"] as! String).replacingOccurrences(of: " ", with: "_")
            //create instance of your class
            if let myClass = NSClassFromString("\(namespace).\(row.name)") as? NameProtocol.Type{
                //init your class
                let classInit : NameProtocol = myClass.init(myArgument: "Hey")
                //classInit is up for use
            }
        }

答案 1 :(得分:1)

将每个单元json存储为其类名

var server *http.Server
//...
func PleaseStart() {
    http.HandleFunc("/", handlerfunc)
    server = &http.Server{
        Addr:    ":80",
        Handler: http.DefaultServeMux,
    }
    log.Fatal(server.ListenAndServe())
}

func kill_server() {
    server.Close()
}

使用@ horusdunord的解决方案从json初始化:

func asDictionary() -> Dictionary<String, Any> {
    let className = String(describing: type(of: self))

    let d = Dictionary<String, Any>(
        dictionaryLiteral:
        ("className", className),

        ("someUnitData", someUnitData),
        // and so on, for all the data of Unit...

这里的诀窍是将类for unitJson in unitsJson { let className = (unitJson as! [String: Any])["className"] as? String let namespace = (Bundle.main.infoDictionary!["CFBundleExecutable"] as! String).replacingOccurrences(of: " ", with: "_") if let unitSubclass = NSClassFromString("\(namespace).\(className ?? "N/A")") as? UnitProtocol.Type { if let unit = unitSubclass.init(json: unitJson as! [String : Any]) { units.append(unit) } else { return nil } } else { return nil } } 转换为unitSubclass然后允许您调用在该协议中声明的UnitProtocol,但在特定子类或其超类{{}中实现1}},如果属性都相同。