はじめに
本記事では、型のキャストについて理解するために内容をまとめます。
キャストとは
値の型を確認し、可能であれば別の型として扱う操作のことをキャストといいます。
型のキャストは、Int型とAny型のように、クラスの継承やプロトコルの準拠などによって階層関係にある型同士で行います。
アップキャスト
階層関係がある型同士において、階層の下位となる具体的な型を上位の抽象的な型として扱う操作を、アップキャストといいます。
アップキャストを行うには、as演算子を使います。
左辺に下位の型の値を指定し、右辺には上位の型を指定します。
上記の例では、String型をAny型にアップキャストし、その結果を定数に代入しています。
Any型はすべての型が暗黙的に準拠しているプロトコルであるため、すべての型はAny型にアップキャスト可能です。
右辺の型が左辺の型の上位互換でない場合、上記のようにコンパイルエラーとなります。
コンパイル可能なアップキャストは常に成功するため、変数や定数への代入時に暗黙的に行うことができます。
このような暗黙的なアップキャストでは、as演算子は必要ありません。
上記の例では、String型の値をAny型に代入することで、as演算子を使わず暗黙的にアップキャストを行なっています。
ダウンキャスト
階層関係のある型同士において、階層の上位となる抽象的な型を下位の具体的な型として扱う操作を、ダウンキャストといいます。
コンパイル可能なアップキャストは常に成功する操作でしたが、ダウンキャストはコンパイル可能でも失敗する可能性があります。
ダウンキャストを行うには、as?演算子、もしくはas!演算子を使用します。
それぞれの演算子の違いは、失敗時の操作にあります。
as?演算子は左辺の値を右辺の型の値にダウンキャストし、失敗した場合はnilを返します。
as?演算子の結果はキャスト先の型の値、もしくはnilとなるため、結果はOptional型となります。
※Optional型についてはこちらの記事でまとめています。
https://qiita.com/wano1101/items/6d2332c3755e84d41200
上記の例では、Any型をString型とInt型にダウンキャストしています。
Any型にアップキャストする前の型はInt型であるため、Int型へのダウンキャストは成功し、その結果はInt?型のOptional(1)となります。
一方、Int型とString型の間に階層関係はないため、String型へのダウンキャストは失敗し、その結果はString?型のnilとなります。
as!演算子によるダウンキャストは強制キャストといいます。
as!演算子は左辺の値を右辺の型にダウンキャストし、失敗した場合は実行時エラーとなります。
上記の例では、Any型の値をString型とInt型の値にダウンキャストしています。
Int型へのダウンキャストは成功し、その結果はInt型の1となります。
一方、String型へのダウンキャストは失敗し、実行時エラーとなります。
型の判定
キャストによって別の型として扱う必要はなく、単にある値の型が特定の型であるかどうかを確認したい場合には、is演算子を使います。
is演算子は左辺に値、右辺に型を取り、値が対象の型かどうかをBool型の値として返却します。
まとめ
- 値の型を確認し、可能であれば別の型として扱う操作のことをキャストという
- 階層の下位となる具体的な型を上位の抽象的な型として扱う操作をアップキャストといい、as演算子を用いる
- 階層の上位となる抽象的な型を下位の具体的な型として扱う操作をダウンキャストといい、as?演算子、もしくはas!演算子を用いる
- as?演算子はダウンキャスト失敗時にnilを返し、as!演算子は強制キャストを行うため失敗時はコンパイルエラーとなる
- is演算子h、値が対象の型かどうかをBool型の値として確認できる