扩展Foundation类以符合Swift协议

时间:2015-12-09 00:43:53

标签: swift protocols foundation

我正在尝试定义一个协议,我想为其添加几个Foundation类的一致性以及我自己的一些自定义类型。我首先尝试使用协议中的便利初始化程序,但是does not seem possible。我在Apple开发论坛上的linked thread读到了他们谈到使用返回类型Self的类方法,但我无法弄清楚如何解决这个问题。

typealias JSONObject = AnyObject
protocol JSONParseable {
    static func fromJSONObject(jsonObject: JSONObject) throws -> Self
}

extension NSURL: JSONParseable {
    class func fromJSONObject(jsonObject: JSONObject) throws -> Self {
        guard let jsonString = jsonObject as? String else {
            throw JSONParseError.ConversionError(message: "blah")
        }
        guard let result = NSURL(string: jsonString) else {
            throw JSONParseError.ConversionError(message: "blah")
        }
        return result // Error: cannot convert return expression of type 'NSURL' to return type 'Self'
    }
}

我找到了一个similar question,但答案是将该课程标记为最终 - 我显然不能在基础课程上这样做。

有人可以解释如何修复上述方法吗?或者建议一种不同的方法来为基础类添加协议一致性?

1 个答案:

答案 0 :(得分:2)

使用self.init(....)代替NSURL(....),因为这也需要适用于NSURL子类。

protocol JSONParseable {
    static func fromJSONObject(jsonObject: JSONObject) throws -> Self
}

extension NSURL : JSONParseable {

    class func fromJSONObject(jsonObject: JSONObject) throws -> Self {

        guard let jsonString = jsonObject as? String else {
            throw JSONParseError.ConversionError(message: "blah")
        }
        guard let result = self.init(string: jsonString) else {
            throw JSONParseError.ConversionError(message: "blah")
        }
        return result
    }
}

Hack:定义typealias T,即使对于子类,也会返回NSURL

protocol JSONParseable {
    typealias T = Self
    static func fromJSONObject(jsonObject: JSONObject) throws -> T
}

extension NSURL : JSONParseable {

    typealias T = NSURL
    class func fromJSONObject(jsonObject: JSONObject) throws -> T {

        guard let jsonString = jsonObject as? String else {
            throw JSONParseError.ConversionError(message: "blah")
        }
        guard let result = NSURL(string: jsonString) else {
            throw JSONParseError.ConversionError(message: "blah")
        }
        return result
    }
}