38

私はSwiftで遊んでいて、辞書に挿入するオブジェクトをダウンキャストすると、奇妙な警告が表示されることを発見しました: Treating a forced downcast to 'String' as optional will never produce 'nil'. に置き換えるasas?、警告が消えます。

func test() -> AnyObject! {
  return "Hi!"
}

var dict = Dictionary<String,String>()
dict["test"]=test() as String

Appleのドキュメントには次のように書かれています

ダウンキャストは失敗する可能性があるため、型キャスト演算子には 2 つの異なる形式があります。オプションの形式 はas?、ダウンキャストしようとしている型のオプションの値を返します。強制形式 はas、ダウンキャストを試み、結果を単一の複合アクションとして強制的にアンラップします。

as?ここで代わりに使用するのasが正しい理由は不明です。いくつかのテストでは、test() を String ではなく Int を返すように変更すると、引き続きas. using に切り替えるとas?、コードは通常どおり実行を継続し、そのステートメントをスキップします (dict は空のままになります)。ただし、なぜこれが好ましいのかはわかりません。私の意見では、プログラムがエラーで終了し、キャストが失敗したことを知らせてから、エラーのあるステートメントを単に無視して実行し続けることをお勧めします。

ドキュメントによると、「ダウンキャストが常に成功することが確実な場合にのみ」強制形式を使用する必要があります。test()この場合、文字列のみを返すことができることがわかっているため、ダウンキャストは常に成功すると確信しているため、これはダウンキャストの強制形式に最適な状況であると想定します。では、なぜコンパイラは警告を出すのでしょうか?

4

3 に答える 3

46

最後の行を詳しく見て、展開して何が起こっているかを見てみましょう。

let temporaryAnyObject = test()
let temporaryString = temporaryAnyObject as String
dict["test"] = temporaryString

エラーは 2 行目にあり、コンパイラに強制するように指示していtemporaryAnyObjectますString。コードは引き続きコンパイルされます (警告をエラーとして扱わないと仮定します) が、temporaryAnyObject実際にはString.

asno を使用した場合の動作方法?は、基本的に「これからは、この式の結果をその型として扱います。結果が実際にその型である場合は、その型として扱います。そうしないと、一貫性がなくなり、実行できなくなります。

as?( を使用して) 動作する方法?は、「これからは、この式の結果をその型として扱います。結果が実際にその型である場合は、この式の結果はnil.

したがって、上記の分解された例では、 iftest()が a を返す場合Stringasダウンキャストは成功し、temporaryString現在はStringです。がaをtest()返さずに、または String からサブクラス化されていないものをString言う場合、 は失敗し、コードは実行を継続できなくなります。Intas

これは、開発者が完全に制御しているため、オプションの?インジケーターを配置しないことで、システムにこのように動作するように指示したためです。このasコマンドは、オプションの動作を許容せず、そのダウンキャストが機能する必要があることを明確に意味します。

を入力した場合は?temporaryStringなりnil、3 行目で「テスト」のキーと値のペアが辞書から単純に削除されます。

これは奇妙に思えるかもしれませんが、これは Obj-C などの多くの言語のデフォルトの動作とは逆であり、デフォルトですべてをオプションとして扱い、独自のチェックとアサートを配置することに依存しているためです。

編集 - Swift 2 アップデート

Swift 2 以降、強制的で失敗可能なダウンキャスト オペレーターasが削除され、as!より Swifter である に置き換えられました。動作は同じです。

于 2014-06-14T20:38:20.557 に答える