この記事ではSwiftの基本ある、キャストについての基本事項を解説していきます。
プログラミングが初心者も、他の言語をやっていてSwiftは初心者という人にもわかるように説明していきたいと思います。
サンプルコードも交えながら説明していきますので、Playgroundを使って実際に手を動かしながら行えると効率よく学習できるかなと思います。
実行環境
MacOS Mojave バージョン10.14.3
Xcode Version 10.2.1
Swift version 5.0.1
型キャストとは
キャストとは変数や定数の型を、より具体的な型や汎用的な型として扱うことです。
例えば、Any型であった変数や定数をInt型として扱ったり、逆にInt型だった変数や定数をAny型として扱うような操作です。
キャストにはアップキャストとダウンキャストの2種類があります。
アップキャストとダウンキャストの違いは、より汎用的な型として扱うのか、具体的な型として扱うかという違いです。
それではそれぞれ説明していきます。
アップキャストとは
アップキャストは、より汎用的な型として扱うことを指します。
例えば、たかし君は東京都民です。
東京都民であるならば、日本人でもあるので、日本人としての振る舞いもします。
このような東京都民から日本人というように、より広いくくりとして扱う場合に、アップキャストを使います。
ではコードで見ていきましょう。
アップキャストを行うときにはasを使用します。
let string: String = "sample"
let any: Any = string as Any //String型からAny型へアップキャスト
上記の例のように、
アップキャストしたい値 as アップキャストする型
という形式で書くことでアップキャストを行うことができます。
ダウンキャストとは
ダウンキャストはより具体的な型として扱うことを指します。
アップキャストとは逆のことをします。
先程のたかし君の例をもう一度考えてみます。
「東京都民であるたかし君は、日本人である」というのが先程の例でしたが、その逆を考えてみます。
「日本人であるたかし君は、東京都民である」
これは、たかし君は東京都民である可能性もありますが、もしかしたら大阪府民である可能性もありますね。
このように、アップキャストの場合は必ず成り立っていたのに対して、ダウンキャストの場合には必ずしも成り立つというわけではありません。失敗する可能性を含んでいます
なので文法としても失敗を含む前提のものとなっているのを前提に置きましょう。
ではコードを見ていきます。
ダウンキャストの書き方はas?かas!を使う2種類の方法があります。
as?を使ったダウンキャスト
as?を使った書き方は以下のようになります。
let any: Any = "sample" as Any
let string = any as? String //Optional("sample")
let int = any as? Int //nil
上記の例の3行目でInt型へダウンキャストをしようとしますが、"sample"はInt型にはなりえないので失敗します。その場合に値がnilとなります。
このように失敗した場合にnilとなるのがas?の特徴です。
それに付随して、2行目を見てみると、こちらはString型へのダウンキャストが成功していますが、値はString型のオプショナル型となっています。
これは失敗する可能性があるので結果がオプショナル型になります。
オプショナル型に関してはこちらの記事で解説していますので、まだ理解できていない人はこちらを参考にしてください。
このようにas?を使用したダウンキャストは結果がオプショナル型となり失敗した場合に結果はnilとなります。
- 結果が
オプショナル型となる - 失敗した場合に結果
nilとなる
as!を使ったダウンキャスト
as!を使ったダウンキャストは以下のように書きます。
let any: Any = "sample" as Any
let string = any as! String //"sample"
let int = any as! Int //実行時エラー
書き方自体はas?の場合と特にそこまで変わってはいませんが、結果が異なります。
2行目がas?の場合にはオプショナル型だったのがString型になっています。
加えて、3行目で実行時エラーとなっています。
オプショナル型が分かる人にはおおよそ検討がついたかもしれませんが、as!を使った場合には結果が強制的にアンラップされて、結果がオプショナル型にならない代わりに、失敗した場合に実行時エラーとなり、アプリがクラッシュします。
as!を使ったダウンキャストを強制キャストといいます。
- 結果が
オプショナル型にはならない - 失敗した場合に実行時エラーとなる
as?とas!のどちらを使うべきか
as?とas!を使ったダウンキャストの方法を解説してきました。
as?は安全である代わりに、失敗したときの処理を書かなければいけません。
対してas!は失敗したときの処理を書かなくていい代わりに、実行時エラーの危険性があります。
どちらも一長一短の特徴を持っていると言えますが、基本的には安全であるas?を使うのがいいかと思います。
しかし、as!を使うほうがむしろ好ましい場面もいくつかあります。
例えばTableViewでTableViewCellを呼び出す際の処理です。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! TableViewCell
return cell
}
ここでは、処理が失敗しない前提というのと、万が一失敗したとしても開発環境の時点でクラッシュしたほうが気づきやすいという利点を考慮してas!と書くようにしています。
上記の例のように、僕らのチームでは、UI周りのパーツのインスタンス化する処理ではas!を使うようにしています。
このように、両方の特徴をしっかり理解した上で、チーム内などで基準を設けたりして適切な方を選ぶことが重要だと思います。
以下はやってはいけないダメな例です。
なんか修正しろってメッセージが出てたから「Fix」を押してみたら解決したので大丈夫だ!って思って実行したら実行時エラーになってしまいます。
ここまで読んでいただいた人はなぜダメなのかもう分かるかと思いますが、このようにしてas!を使うのは不安定なコードになりやすいので注意です。
まとめ
今回は、型キャストに関してまとめていきました。
型キャストはSwiftの基本事項なのでしっかり押さえておきましょう。
Swiftの入門記事に関してはこちらにまとめていますので参考にしてみてください。