問題は、コンパイラがあなたが守ることを証明できないという約束をしているということです。
したがって、この約束を作成しました。呼び出しcopy()
は、完全に初期化された独自の型を返します。
しかし、あなたはcopy()
このように実装しました:
func copy() -> Self {
return C()
}
今、私はオーバーライドしないサブクラスですcopy()
。そしてC
、完全に初期化されたものではなく、を返しますSelf
(約束しました)。だからそれは良くない。どうですか:
func copy() -> Self {
return Self()
}
まあ、それはコンパイルされませんが、コンパイルされたとしても、それは良くないでしょう。サブクラスには簡単なコンストラクターD()
がない可能性があるため、合法ではない可能性もあります。(以下を参照してください。)
OK、まあどうですか:
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) {
}
}
ここでは、コピーを実行するイニシャライザーがあることを約束します。次に、実行時に呼び出すイニシャライザーを決定して、探していたメソッド構文を取得できます。