[解決済み] プロトコルは自分自身に適合しない?
質問
なぜこのSwiftコードはコンパイルできないのでしょうか?
protocol P { }
struct S: P { }
let arr:[P] = [ S() ]
extension Array where Element : P {
func test<T>() -> [T] {
return []
}
}
let result : [S] = arr.test()
コンパイラは次のように言っています: "タイプ
P
はプロトコルに適合していません。
P
"(または、Swiftの後のバージョンでは、"プロトコル 'P' に準拠した具象型として 'P' を使用することはサポートされていません.")。
なぜダメなのでしょうか?これは、何となく、言語の穴のように感じます。私は、この問題は、配列
arr
を配列として
をプロトコル型の
というのがありますが、これは不合理なことなのでしょうか?プロトコルは、構造体に型階層のようなものを提供するために存在するのでは?
どのように解決するのですか?
編集:Swiftでの作業でさらに18ヶ月、別のメジャーリリース(新しい診断を提供する)、そして@AyBayBayからのコメントで、この答えを書き直したくなりました。新しい診断は
"プロトコル 'P' に準拠した具象型として 'P' を使用することはサポートされていません."
これで実際、この件がかなり明確になりましたね。このエクステンションは
extension Array where Element : P {
が適用されないのは
Element == P
から
P
の具体的な適合性とはみなされないからです。
P
. (以下の "put it in a box" ソリューションはまだ最も一般的なソリューションです)。
古い回答です。
それはまた別のメタタイプのケースです。Swift
は本当に
は、ほとんどの非自明な事柄のために具象型に到達することを望んでいます。
(実際にはそうではないと思います。サイズ
[P]
は具象型ではありません (既知の大きさのメモリブロックを
P
).
P
なぜなら
というのは、それはインダイレクトで行われるからです。
.) これが "shouldn't" のケースであるという根拠はないと思うのですが。これは、彼らの "doesn't work yet" ケースのひとつに非常によく似ているようです。(残念ながら、これらのケースの違いをAppleに確認させることはほとんど不可能です)。という事実は
Array<P>
が変数型になりうるということです (ここで
Array
はできない) は、彼らがすでにこの方向でいくつかの仕事をしたことを示しますが、Swift のメタタイプは鋭いエッジと未実装のケースがたくさんあります。私はあなたがそれよりも良い"なぜ"答えを得るつもりはないと思います。 "コンパイラがそれを許可していないからです。
解決策は、ほとんどの場合、物事を箱に入れることです。タイプイレイザーを作るのです。
protocol P { }
struct S: P { }
struct AnyPArray {
var array: [P]
init(_ array:[P]) { self.array = array }
}
extension AnyPArray {
func test<T>() -> [T] {
return []
}
}
let arr = AnyPArray([S()])
let result: [S] = arr.test()
Swift がこれを直接できるようにするとき (私はいずれそうなることを期待しています)、それはおそらく、あなたのためにこのボックスを自動的に作成することだけになるでしょう。再帰的な列挙はまさにこの歴史を持っていました。あなたはそれらをボックス化しなければならず、それは信じられないほど迷惑で制限的でした。そして最終的にコンパイラは
indirect
を追加して、同じことをより自動的に行うようにしました。
関連
-
[解決済み] Xcode 8 シェルスクリプト呼び出しエラー
-
[解決済み] swift 3 エラー。引数ラベル '(_:)' は利用可能なオーバーロードに一致しません。
-
[解決済み] Swift Optionals - 条件の変数バインディングはイニシャライザを必要とする
-
[解決済み] Swift 3でdispatch_onceはどうなる?
-
[解決済み] Swift stdlib ツール エラー
-
[解決済み] 純粋な」Swift で弱いプロトコル参照を作るには (@objc なしで) どうしたらいいですか?
-
[解決済み] Swiftの'open'キーワードは何ですか?
-
[解決済み】Swiftで弱参照の配列を宣言するには?
-
[解決済み】swift言語におけるstructureとclassの比較
-
[解決済み] 配列からオブジェクトを探す?
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】インスタンスメンバを型で使用することができない
-
[解決済み] テスト
-
[解決済み] このコンテキストで型検索を行う場合、「メソッド」は曖昧である、Alamofireのエラー
-
[解決済み] swiftにおけるconvenience initとinitの違いは何ですか、より良い明示的な例
-
[解決済み] Swiftではクロージャの内部では常に[unowned self]を使うべきか?
-
[解決済み] Swiftで乱数を生成する方法とは?
-
[解決済み] Swift で app delegate への参照を取得するにはどうすればよいですか?
-
[解決済み】コンパイラーエラー。Objective-C のセレクタを持つメソッドは、同じ Objective-C セレクタを持つ以前の宣言と競合しています。
-
[解決済み】swift言語におけるstructureとclassの比較
-
[解決済み】Xcode 8 Beta 3 Legacy Swiftを使用する問題