我有以下协议
protocol JSONInitializable {
static func initialize(fromJSON: NSDictionary) throws -> Self?
}
现在我试图使该函数返回任何符合协议的类。即如果我有符合协议的类Foo
,我想从该方法返回一个Foo
对象。我怎么能这样做?
extension Foo: JSONInitializable {
static func initialize(fromJSON: NSDictionary) throws -> Foo? {
}
}
我收到错误:
方法'初始化'在非决赛阶段' Foo'必须回归' Self'遵守协议' JSONInitializable'
答案 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
方法时编写它,那么如果我们将Foo
与Bar
子类化,那么现在我们已经破坏了我们的一致性协议。 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
}
}