在swift中,如何返回符合协议的相同类型的对象

时间:2016-03-28 22:38:05

标签: swift return-value swift-protocols

我有以下协议

protocol JSONInitializable {
    static func initialize(fromJSON: NSDictionary) throws -> Self?
}

现在我试图使该函数返回任何符合协议的类。即如果我有符合协议的类Foo,我想从该方法返回一个Foo对象。我怎么能这样做?

extension Foo: JSONInitializable {
    static func initialize(fromJSON: NSDictionary) throws -> Foo? {
    }
}

我收到错误:

  

方法'初始化'在非决赛阶段' Foo'必须回归' Self'遵守协议' JSONInitializable'

2 个答案:

答案 0 :(得分:3)

自动填充功能会对您有所帮助,但基本上,如果Foo是一个类,您只需要一个与协议中方法的确切签名相匹配的方法:

class Foo {}

protocol JSONInitializable {
    static func initialize(fromJSON: [String : AnyObject]) throws -> Self?
}

extension Foo: JSONInitializable {
    static func initialize(fromJSON: [String : AnyObject]) throws -> Self? {
        return nil
    }
}

在此处注意,您必须在此方法中将Foo的所有实例替换为Self。如果要使用构造函数,则必须将其标记为必需。

考虑到这一点,将协议更改为需要初始化程序而不是名为initialize的静态方法可能更有意义,在这种情况下,请查看Blake Lockley's answer。但是,这个答案可以回答如何在协议中处理Self的问题,因为在某些情况下我们可能需要一个返回Self并不是初始值的方法。< / p>

如果Foo不是类,则它是一个不能是子类的值类型,因此,我们返回该类型的名称:

struct Foo: JSONInitializable {
    static func initialize(fromJSON: [String : AnyObject]) throws -> Foo? {
        return nil
    }
}
enum Foo: JSONInitializable {
    case One, Two, Three

    static func initialize(fromJSON: [String : AnyObject]) throws -> Foo? {
        return nil
    }
}

在类的情况下,需要从方法返回Self?的原因是继承。该协议声明如果你符合它,你将有一个名为initialize的方法,其返回类型将是你的任何可选版本。

如果我们在编写Foo initialize方法时编写它,那么如果我们将FooBar子类化,那么现在我们已经破坏了我们的一致性协议。 Bar继承了Foo对协议的一致性,但它没有一个名为initialize并返回Bar?的方法。它有一个返回Foo

在这里使用Self意味着当我们的子类继承此方法时,它将返回它们的任何类型。 Self是Swift相当于Objective-C's instancetype

答案 1 :(得分:1)

如nhgrif中所述,将Foo?的返回类型更改为self?

<强>替代地

在Swift中你可以在协议中声明init,所以尝试这样的事情:

protocol JSONInitializable {
    init?(fromJSON: NSDictionary) throws
}

extension Foo: JSONInitializable {
    required init?(fromJSON: NSDictionary) throws {
      //Possibly throws or returns nil
    }
}