我有一个协议P,它返回对象的副本:
protocol P { func copy() -> Self }
和一个实现P的类C:
class C : P { func copy() -> Self { return C() } }
但是,是否Self在出现以下错误时放入返回值:
Self
无法将类型“ C”的返回表达式转换为类型“ Self”
我也试着回来C。
C
class C : P { func copy() -> C { return C() } }
这导致以下错误:
非最终类“ C”中的方法“ copy()”必须返回Self以符合协议“ P”
除了我class C以finalie做前缀的情况外,没有任何作用:
class C
final
final class C : P { func copy() -> C { return C() } }
但是,如果我想对C进行子类化,那么将无济于事。有没有办法解决?
问题是您要保证编译器无法证明您会保留。
因此,您创建了以下承诺:调用copy()将返回其自身的类型,并进行完全初始化。
copy()
但是随后您实现了copy()这种方式:
func copy() -> Self { return C() }
现在我是一个不会重写的子类copy()。然后返回C,而不是完全初始化的Self(我保证)。那就不好了 怎么样:
func copy() -> Self { return Self() }
好吧,那不会编译,但是即使编译了,也没有好处。子类可能没有琐碎的构造函数,因此D()甚至可能不合法。(尽管请参见下文。)
D()
好的,怎么样:
func copy() -> C { return C() }
是的,但这不会返回Self。它返回C。您仍然没有遵守诺言。
“但是ObjC可以做到!” 好吧,有点。主要是因为它并不关心您是否像Swift那样信守诺言。如果无法copyWithZone:在子类中实现,则可能无法完全初始化对象。编译器甚至不会警告您已完成该操作。
copyWithZone:
“但是ObjC中的大多数内容都可以翻译成Swift,而ObjC可以NSCopying。” 是的,它的定义方式如下:
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,而且我还没有对其进行广泛的测试以确保它始终是我们想要的,但是它应该是正确的:
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. } }
在这里,我们保证有一个初始化程序为我们执行拷贝,然后我们可以在运行时确定要调用的那个,从而为我们提供了您要查找的方法语法。