当前位置: 首页 > 面试题库 >

协议功能返回自我

胡新
2023-03-14
问题内容

我有一个协议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 Cfinalie做前缀的情况外,没有任何作用:

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

但是,如果我想对C进行子类化,那么将无济于事。有没有办法解决?


问题答案:

问题是您要保证编译器无法证明您会保留。

因此,您创建了以下承诺:调用copy()将返回其自身的类型,并进行完全初始化。

但是随后您实现了copy()这种方式:

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

现在我是一个不会重写的子类copy()。然后返回C,而不是完全初始化的Self(我保证)。那就不好了 怎么样:

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

好吧,那不会编译,但是即使编译了,也没有好处。子类可能没有琐碎的构造函数,因此D()甚至可能不合法。(尽管请参见下文。)

好的,怎么样:

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

是的,但这不会返回Self。它返回C。您仍然没有遵守诺言。

“但是ObjC可以做到!”
好吧,有点。主要是因为它并不关心您是否像Swift那样信守诺言。如果无法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.
  }
}

在这里,我们保证有一个初始化程序为我们执行拷贝,然后我们可以在运行时确定要调用的那个,从而为我们提供了您要查找的方法语法。



 类似资料:
  • 问题内容: 我正在使用swift 2.0,我有一个协议和对该协议的扩展来创建方法的默认实现,代码如下: 稍后,我在代码中尝试调用此方法,并收到一条错误消息: “不能在不可变值上使用变异成员:’自身’是不可变的” 代码如下: 我唯一想到的是这种情况下的“ Self”是协议,而不是类。但是,我必须缺少一些东西才能使该概念起作用。该协议定义的方法的默认实现,该方法还可以编辑同一协议定义的值。 谢谢您的帮

  • cmf_get_domain() 功能 返回带协议的域名 参数 无 返回 string

  • 返回当前运行的whisper版本。 调用: web3.shh.getVersion([callback]) 参数: callback:Function - 可选的回调函数,其第一个参数为错误对象,第二个参数为结果 返回值: String - 当前运行中的whisper版本 示例代码: web3.shh.getVersion() .then(console.log); > "5.0"

  • 返回节点旳以太坊协议版本。 调用: web3.eth.getProtocolVersion([callback]) 返回值: 一个Promise对象,其解析值为协议版本字符串。 示例代码: web3.eth.getProtocolVersion().then(console.log); > "63"

  • 函数也可以将值与控件一起返回给调用者。 这些函数称为returning functions 。 语法 (Syntax) return_type function_name(){ //statements return value; } return_type可以是任何有效的数据类型。 return语句是可选的。 我没有指定函数返回null; 返回值的数据类型必须与函数的返

  • 问题内容: 当我尝试在http://golang.org/pkg/net/http/#example_Get上运行此示例时,它返回以下错误 2009/11/10 23:00:00获取http://www.google.com/robots.txt:拨打tcp:协议不可用 知道为什么吗? 问题答案: Go Playground不允许HTTP请求。这与代码无关。这是操场强制执行的安全预防措施。