为了账号安全,请及时绑定邮箱和手机立即绑定

协议函数返回自

/ 猿问

协议函数返回自

偶然的你 2019-07-13 10:07:31

协议函数返回自

我有一个协议P,它返回对象的副本:

protocol P {
    func copy() -> Self}

以及实现P的类C:

class C : P {
    func copy() -> Self {
        return C()
    }}

但是,是否将返回值作为Self我得到以下错误:

无法将“C”类型的返回表达式转换为返回类型“Self”

我也试着回去C.

class C : P {
    func copy() -> C  {
        return C()
    }}

这导致以下错误:

非终级“C”中的方法“Copy()”必须返回Self遵守“P”协议

除了我前缀的情况外,什么都不起作用。class C带着final(如:

final class C : P {
    func copy() -> C  {
        return C()
    }}

但是,如果我想要子类C,那么什么都不能工作。有办法绕过这件事吗?


查看完整描述

3 回答

?
Cats萌萌

问题是,您正在做出编译器无法证明您将遵守的承诺。

所以你创造了这样的承诺:copy()将返回自己的类型,完全初始化。

但是你实现了copy()这样:

func copy() -> Self {
    return C()}

现在我是一个不覆盖的子类copy()..我还给你一个C,而不是完全初始化Self(这是我答应过的)。所以这样不好。不如:

func copy() -> Self {
    return Self()}

嗯,这不会编译,但即使编译了,也是没有好处的。子类可能没有简单的构造函数,因此D()甚至可能是不合法的。(尽管见下文)

好吧,那么:

func copy() -> C {
    return C()}

是的,但那不会回来Self..它回来了C..你还是没信守诺言。

“但是objc可以做到!”算是吧。主要是因为它不在乎你是否像斯威夫特那样信守诺言。如果你不能实现copyWithZone:在子类中,可能无法完全初始化对象。编译器甚至不会警告您已经这样做了。

“但是objc中的大多数东西都可以翻译成SWIFT,而objc有NSCopying“是的,它是这样定义的:

func copy() -> AnyObject!

所以你可以做同样的(没有理由!)在此):

protocol Copyable {
  func copy() -> AnyObject}

上面写着“我不会保证你会得到什么。”你也可以说:

protocol Copyable {
  func copy() -> Copyable}

这是你可以做出的承诺。

但是我们可以考虑一下C+,记住我们有一个承诺能,会,可以制作,使。我们可以保证,我们和所有子类都将实现特定类型的初始化器,SWIFT将强制执行这一点(因此可以证明我们说的是实话):

protocol Copyable {
  init(copy: Self)}class C : Copyable {
  required init(copy: C) {
    // Perform your copying here.  }}

这就是你应该做的拷贝。

我们可以更进一步,但是dynamicType,我还没有对它进行广泛的测试,以确保这始终是我们想要的,但它应该是正确的:

protocol Copyable {
  func copy() -> Self
  init(copy: Self)}class C : Copyable {
  func copy() -> Self {
    return self.dynamicType(copy: self)
  }

  required init(copy: C) {
    // Perform your copying here.  }}

在这里,我们保证有一个初始化程序为我们执行副本,然后我们可以在运行时确定要调用哪一个,给出您要寻找的方法语法。


查看完整回答
反对 回复 2019-07-13
?
MMTTMM

使用SWIFT 2,我们可以使用协议扩展。

protocol Copyable {
    init(copy:Self)}extension Copyable {
    func copy() -> Self {
        return Self.init(copy: self)
    }}


查看完整回答
反对 回复 2019-07-13
?
胡说叔叔

还有一种方法可以实现你想做的事情,那就是利用SWIFT的关联类型。下面是一个简单的例子:

public protocol Creatable {

    associatedtype ObjectType = Self

    static func create() -> ObjectType}class MyClass {

    // Your class stuff here}extension MyClass: Creatable {

    // Define the protocol function to return class type    static func create() -> MyClass {

         // Create an instance of your class however you want        return MyClass()
    }}let obj = MyClass.create()


查看完整回答
反对 回复 2019-07-13
  • 3 回答
  • 0 关注
  • 181 浏览
我要回答

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信