[解決済み] 自己を返すプロトコルfunc
質問
オブジェクトのコピーを返すプロトコルPがあります。
protocol P {
func copy() -> Self
}
と、Pを実装したクラスCがあります。
class C : P {
func copy() -> Self {
return C()
}
}
しかし、戻り値を
Self
というエラーが出ます。
型 'C' の return 式を型 'Self' の return 式に変換することができません。
また
C
.
class C : P {
func copy() -> C {
return C()
}
}
その結果、以下のようなエラーが発生しました。
非終端クラス 'C' のメソッド 'copy()' は、必ず
Self
に適合するように を返さなければなりません。
をプレフィックスとする場合を除き、何も動作しません。
class C
と
final
を行う。
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()
は合法ではないかもしれません。(以下を参照してください)。
OK、ではどうでしょう。
func copy() -> C {
return C()
}
はい、でもこれでは
Self
. それは
C
. まだ約束を守ってないのか。
しかし、ObjCはそれができるのです!" まあ、そんなところです。ほとんどの場合、Swiftがそうであるように、あなたが約束を守るかどうかを気にしないためです。もし、あなたが
copyWithZone:
をサブクラスで実装することに失敗した場合、オブジェクトを完全に初期化することに失敗する可能性があります。コンパイラは、それを行ったことを警告することさえしません。
"しかし、ObjCのほとんどのものはSwiftに翻訳することができ、ObjCには
NSCopying
."そうです、そしてこれがどのように定義されているかです。
func copy() -> AnyObject!
ということで、同じようにできます(ここでは「!」の理由はありません)。
protocol Copyable {
func copy() -> AnyObject
}
That says "I'm not promising anything about what you get back."とも言えるでしょう。
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 で弱いプロトコル参照を作るには (@objc なしで) どうしたらいいですか?
-
[解決済み] swiftにおけるプロトコルの配列型および関数パラメータとしての使用法
-
[解決済み] Protocol ... can only be used as generic constraint because it has Self or associated type requirements "とは、どういう意味ですか?
-
[解決済み] 既存のUIKitアプリケーションにSwiftUIビューを含める
-
[解決済み] 小数点以下2桁に切り上げ
-
[解決済み] SwiftでNSDatesの秒数の差を整数値で求める。
-
[解決済み] Swiftの関数パラメータとしてのプロトコルに準拠したクラス
-
[解決済み] Codableクラスはプロトコルに準拠していない Decodable
-
[解決済み] Swiftの定数。構造体か列挙型か
-
[解決済み] iOS 9のスワイプ可能なテーブルビューセル
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
Swift の Optional 値 && Optional のアンラップ時に予期せず nil が検出された場合の説明
-
[解決済み] Swiftスクリプトでターミナルコマンドを実行するには?(例:xcodebuild)
-
[解決済み] Xcode 8.3 betaの「String interpolation produces a debug description for an optional value; did you mean to make this explicit?
-
[解決済み] NSFetchRequestのインスタンスに型を適用する方法は?
-
[解決済み] Swift- Remove Push Notification Badge number?
-
[解決済み] Swiftでenumをプロトコルに準拠させるには?
-
[解決済み] Swiftで失敗しないイニシャライザーを実装するためのベストプラクティス
-
[解決済み] Swift で CGFloat を切り上げる
-
[解決済み] Swiftの定数。構造体か列挙型か
-
[解決済み] SceneDelegateとAppDelegateの違いについて