问题是您做出了编译器无法证明您会遵守的承诺。
所以你创建了这个承诺:调用copy()
将返回它自己的类型,完全初始化。
但是后来你copy()
以这种方式实现了:
func copy() -> Self {
return C()
}
现在我是一个不覆盖的子类copy()
。我返回 a 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.
}
}
在这里,我们保证有一个初始化器为我们执行复制,然后我们可以在运行时确定调用哪个初始化器,为我们提供您正在寻找的方法语法。