Swift 6.0 beta 日本語化計画 : Swift 6.0 beta
型キャスト
型キャスト(タイプキャスト) は、インスタンスの型をチェックし、または独自のクラス階層内の別の場所から別のスーパークラスまたはサブクラスとしてそのインスタンスを扱うための方法です。
Swift の型キャストは、is と as 演算子として実装されています。これら2つの演算子は、値の型を確認するか、別の型に値をキャストするためのシンプルで表現豊かな方法を提供します。
また、プロトコル準拠の確認 で説明したように、型がプロトコルに準拠しているかどうかチェックするために型キャストを使用することもできます。
特定のクラスインスタンスの型をチェックし、同じ階層内の別のクラスにそのインスタンスをキャストするクラスとサブクラスの階層で型キャストを使用できます。以下の3つのコードスニペットは、クラスの階層と型キャストの例で使用するためのそれらのクラスのインスタンスを含む配列を定義しています。
最初のスニペットは MediaItem という新しい基本クラスを定義します。このクラスは、デジタルメディアライブラリに表示された項目の全ての種類の基本的な機能を提供しています。具体的には、String 型の name プロパティと init(name:) イニシャライザを宣言しています。(これは、すべての映画や曲を含むすべてのメディア項目は、名前を持っていると想定しています。)
次のスニペットは MediaItem の2つのサブクラスを定義しています。最初のサブクラス、Movie は、映画やフィルムに関する追加情報をカプセル化します。対応するイニシャライザで、基本の MediaItem クラスの最上部に director プロパティを追加します。第二のサブクラス、Song は、基底クラスの最上部に、artist プロパティとイニシャライザを追加します。
最後のスニペットは、2つの Movie インスタンスと3つの Song インスタンスを含む library と言う定数の配列を作成します。library 配列の型は、配列リテラルの内容でそれを初期化することにより推測されます。Swift の型チェッカーはその Movie と Song が MediaItem の共通のスーパークラスを持っている事を推測することができ、それで library 配列の [MediaItem] 型を推測します:
library に格納されている項目は、舞台裏ではまだ Movie と Song インスタンスです。しかし、この配列の内容を繰り返し処理した場合、受け取る項目は MediaItem としての型であり、Movie や Song としてではありません。それらの特有の型としてそれらを処理するには、下記のように、それらの型を チェック して、または別の型にそれらを ダウンキャスト する必要があります。
インスタンスが特定のサブクラスの型であるかどうかをチェックするためには 型チェック演算子 (is) を使用して下さい。インスタンスがそのサブクラスの型であれば、型チェック演算子は true を返し、そうでない場合、false を返します。
以下の例では、library 配列内の Movie と Song のインスタンスの数を数える2つの変数、movieCount と songCount を定義しています。
この例は、library 配列内のすべての項目を反復処理します。各パスで、for-in ループは配列内の次の MediaItem に item 定数を設定します。
item is Movie は、現在の MediaItem が Movie インスタンスの場合 true を返し、そうでない場合、false を返します。同様に、item is Song は項目が Song インスタンスであるかどうかをチェックします。for-in ループの終わりに、movieCount と songCount の値は、各型の MediaItem インスタンスがどれだけ多く発見されたかの数を含んでいます。
特定のクラスの型の定数または変数は、実際には舞台裏ではサブクラスのインスタンスを参照しているかもしれません。このような場合、型キャスト演算子 (as? または as!) でサブクラス型に ダウンキャスト しようとすることができます。
ダウンキャストは失敗することがあるので、型キャスト演算子は、二つの異なる形式で提供されます。条件付きの形式は、as? で、ダウンキャストしようとしている型の optional の値を返します。強制的な形は、as! で、ダウンキャストを試み、単一の複合アクションとして結果を強制開封します。
ダウンキャストが成功するかどうかわからない時には、型キャスト演算子 (as?) の条件付き形式を使用して下さい。演算子のこの形式は、常に optional の値を返し、ダウンキャストが不可能であった場合、値は nil になります。これで、ダウンキャストが成功したかどうかをチェックできます。
ダウンキャストが常に成功すると確信している場合にのみ、型キャスト演算子の強制的な形式 (as!) を使用して下さい。正しくないクラス型へダウンキャストしようとした場合、演算子のこの形式は、実行時エラーを引き起こします。
以下の例では、library 内の各 MediaItem を反復処理し、各項目の適切な説明を出力します。これを行うには、単に MediaItem としてではなく、真の Movie や Song として各項目にアクセスする必要があります。その説明で使用するための Movie や Song の director や artist プロパティにアクセスできるようにするためにこれは必要です。
以下の例では、配列内の各項目は、Movie である場合もあれば、Song である場合もあります。各項目に使用する実際のクラスは、事前にはわからないので、ループを通じて毎回ダウンキャストをチェックするには、型キャスト演算子 (as?) の条件付きの形を使用することが適切です:
この例では、Movie として現在の item をダウンキャストしようとして始まります。item は MediaItem インスタンスなので、それは Movie かも しれません。同じように、それはまた Song かもしれませんし、あるいは基本の MediaItem かもしれません。この不確実性のため、as? 形式の型キャスト演算子は、サブクラス型にダウンキャストしようとすると optional の値を返します。item as? Movie の結果は、Movie? 型か、または "optional の Movie" です。
library 配列内の Song インスタンスに適用された場合には Movie にダウンキャストする事は失敗します。これに対処するため、上記の例では、optional の Movie が、実際に値を含む (つまり、ダウンキャストが成功したかどうかを調べる) か確認するために、optional の結合を使います。この optional の結合は "if let movie = item as? Movie" と書かれており、こう読めます:
"Movie として item にアクセスしてみました。これが成功すれば、戻された optional の Movie に格納されている値に movie と言う新しい一時的定数を設定します。" と。
ダウンキャストが成功すると、movie のプロパティは、その director の名前を含め、その Movie インスタンスの説明を印刷するために使用されます。同様の原理は、Song> インスタンスをチェックするためと、そして Song が library で発見されるたびに (artist 名を含む) 適切な説明を印刷するために使用されます。
Swift は、非特定の型を操作するための二つの特別な型を提供します。
明示的にそれらが提供する動作や能力を必要な場合にのみ、Any と AnyObject を使用してください。コード内で動作するように期待する型について特別であるのが常により良い事です。
ここで関数型と非クラス型を含む、異なる型の混合で動作するように Any を使用する例を挙げます。この例では、Any 型の値を格納できる things と言う配列を作成します。
things 配列は、2つの Int 値、2つの Double 値、一つの String 値、(Double,Double) 型のタプル、映画 "ゴーストバスターズ"、および String 値を取り、別の String 値を返すクロージャ式を含んでいます。
Any または AnyObject 型のいずれかでしかないと知られている定数または変数の特定の型を発見するには、switch 文の case の is と as パターンを使う事ができます。以下の例は、things 配列内の項目を繰り返し処理し、switch 文で各項目の型を照会します。switch 文の case のいくつかは、その値を印刷するのを有効にするために、指定された型の定数に、その一致した値を結合します: