Swift在泛型中使用Self&协议(无方法级初始化)

时间:2017-02-28 01:40:14

标签: swift generics

更新 这个问题投票决定关闭这个,因为重复处理self.init(),可以通过标记类final或需要init来解决。但是,如何处理存储库或从init以外的任何其他方法返回(我的实现是@NSManaged对象)

这是我想要做的。通过请求获取JSON,然后将其解析为对象。

var req = Request("http://somewhere/story/get/1")
var story = req.parseJsonResponse() as Story

Request类看起来像这样:

class Request {

    public var httpJsonResponse : String

    init(_ url : String) {
        //This comes from HTTP
        httpJsonResponse = "{}"
    }

    public func parseJsonResponse<T : IParse>() -> T {

        return T.parse(json: httpJsonResponse)

    }

}

现在,我想确保IParse实现具有解析方法:

protocol IParse {
    static func parse(json : String) -> Self
}

到目前为止一直很好,这是实施的问题:

class Story : IParse {
    required init() 
    {
    }
    public static func parse(json: String) -> Self
    {
        //return self.init() works thanks to @tomahh
        return StoryRepo.ById(1)
    }

}

class StoryRepo {
    public static func ById(_ id : Int) -> Story {
        return Story()
    }
}

这不起作用。这些都不起作用:

  1. 回归故事
  2. 投射Story() as! Self
  3. 查看更新后的游乐场gist

1 个答案:

答案 0 :(得分:1)

class Story : IParse {
    required init() 
    {
    }

    public static func parse(json: String) -> Self
    {
        return self.init()
    }
}

这会奏效。这确保您实际构建Self的实例,以便Tale的{​​{1}}子类不会创建无聊的Story,但确实是一个美妙的故事。

Story关键字强制子类覆盖此init,因此我们确信在解析中实际调用required是有效的。

另一个解决方案,如果您不想继承,那就是self.init()Story

final

在此示例中,由于永远不会继承final Story: IParse { public static func parse(json: String) -> Story { return Story() } } ,因此可以安全地调用Story并从Story()函数返回Story类型。