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

在swift中,如何返回符合协议的相同类型的对象,swift,return-value,swift-protocols,Swift,Return Value,Swift Protocols,我有以下协议 protocol JSONInitializable { static func initialize(fromJSON: NSDictionary) throws -> Self? } 现在我试图让这个函数返回任何符合协议的类。也就是说,如果我的类Foo符合协议,我想从方法返回Foo对象。我该怎么做 extension Foo: JSONInitializable { static func initialize(fromJSON: NSDictionar

我有以下协议

protocol JSONInitializable {
    static func initialize(fromJSON: NSDictionary) throws -> Self?
}
现在我试图让这个函数返回任何符合协议的类。也就是说,如果我的类
Foo
符合协议,我想从方法返回
Foo
对象。我该怎么做

extension Foo: JSONInitializable {
    static func initialize(fromJSON: NSDictionary) throws -> Foo? {
    }
}
我得到一个错误:

非最终类“Foo”中的方法“initialize”必须返回“Self”以符合协议“JSONInitializable”


自动完成将对您有所帮助,但基本上,如果
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
的静态方法可能更有意义,在这种情况下,请查看。然而,这个答案回答了如何在协议中处理
Self
的问题,因为在某些情况下,我们可能需要返回非初始值设定项的
Self
的方法


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

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

对于类,需要从方法返回
Self?
的原因是继承。该协议声明,如果您遵守它,您将有一个名为
initialize
的方法,其返回类型将是您所属内容的可选版本

如果我们像您编写的那样编写
Foo
initialize
方法,那么如果我们使用
Bar
Foo
进行子类化,那么现在我们已经破坏了对协议的一致性
Bar
继承了来自
Foo
的协议一致性,但它没有名为
initialize
并返回
Bar?
的方法。它有一个返回
Foo


在这里使用
Self
意味着当我们的子类继承这个方法时,它将返回它们的任何类型
Self
是Swift的等价物。

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

或者

在Swift中,您可以在协议中声明
init
s,因此请尝试以下操作:

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

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

因此,这将允许我从方法返回类型为
Foo
的对象?如果在
Foo
的实例上调用它,它将返回
Foo
。如果您将
Foo
子类化为
class Bar:Foo
,它将返回
Bar
。我刚刚尝试了这个方法,现在当我尝试从该方法返回
Foo
类型的对象时,它给出了一个错误。它说,
无法将类型为“Foo”的表达式转换为返回类型为“Self”
我使用的是xcode 7.3,如果这有帮助的话,在这种方法中,您必须将
Foo
的所有引用替换为
Self
。如果你想使用一个构造函数,它必须是一个标记为
必需的
。嗯,我有点不知道怎么做。我想做
让f=Foo();返回f
。这就产生了错误。然后我尝试返回f.self()另一个错误。因此,我不确定现在返回什么,我认为您需要
便利性
必需
在该扩展中,您需要
必需
。您不一定需要方便。还值得一提的是,Objective-C协议可以声明初始值设定项是协议的一部分。为了进一步阅读,。我只是尝试了这种方式,错误是我只能在非最终类的定义中这样做,即扩展不适用于进一步阅读
required
关键字以及为什么需要它,@Smac89您在扩展之前已经声明了
Foo
类了吗?如果没有,您可以在实现中包含协议,而不使用这样的扩展:
Foo:JSONInitializable{required init?…}
protocol JSONInitializable {
    init?(fromJSON: NSDictionary) throws
}

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