问题是您要保证编译器无法证明您会保留。
因此,您创建了以下承诺:调用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) {
}
}
这就是您应该执行复制的方式。
我们可以进一步迈出这一步,但是它使用了dynamicType
,而且我还没有对其进行广泛的测试以确保它始终是我们想要的,但是它应该是正确的:
protocol Copyable {
func copy() -> Self
init(copy: Self)
}
class C : Copyable {
func copy() -> Self {
return self.dynamicType(copy: self)
}
required init(copy: C) {
}
}
在这里,我们保证有一个初始化程序为我们执行拷贝,然后我们可以在运行时确定要调用的那个,从而为我们提供了您正在寻找的方法语法。