キャンペーンの今のうちに是非!!↓


⇒「ひろゆき『1%の努力』を無料で見る方法

【Swift奮闘記ep27】型のキャスト前半(アップキャスト、ダウンキャスト、型のチェック)

IPhoneアプリ作成Swift奮闘記

この本を見ながら進めてる↓

前回⇒「【Swift奮闘記ep26】クロージャ後半(クロージャ式を引数や戻り値で使う、省略記法、末尾のクロージャ、クロージャとは)

第5章の締めは型のキャスト。

型のキャストとは2つの機能のことを言う。

1つ目は「あるインスタンスが、ある特定の型であるかどうかをチェックする機能」

2つ目は「あるインスタンスを、特定の型のインスタンスに変換する機能」

アップキャスト

あるクラスのインスタンスを、スーパークラスのインスタンスにキャストすること」をアップキャストという。

アップキャストを行うと、対象のインスタンスを、そのインスタンスのクラスのスーパークラスからインスタンス化されたものとして扱う事が出来る。

ふうむ・・・。いまいちわからん。

具体的にコードを見ていこう。


Foodというクラス、Foodを継承したNoodleというクラス、Foodを継承したCurryというクラス、の3つのクラスが定義してある。

それぞれname,soup,spicyという独自のプロパティが定義されている。

まずはNoodleとCurryをインスタンス化してみる。


2つの定数noodle,curryができた。これらは別のクラスであるが、スーパークラスは両方ともFoodである。

そういうときにアップキャストを使えばこの2つのインスタンスはFoodクラスのインスタンスとして扱う事が出来るよ、という事だ。


インスタンスの後に「as クラス」としてやれば、スーパークラスのFoodとしてインスタンスは扱われるわけだ。

つまりfoodAはnameプロパティだけ使えるようになり、soupプロパティは使えない。

同じように、foodBもnameは使えるがspicyは使えない。

コンパイルエラーとなっているのがわかる。

さらに以下のように予めスーパークラスが指定されているところに変数や定数を代入すると、自動的にアップキャストが行われる。


asを使うアップキャストよりこちらの方がよく使われる。

ダウンキャスト

あるクラスのインスタンスを、そのクラスのサブクラスのインスタンスにキャストすること」をダウンキャストという。

先ほどと同様に3つのクラスを用意する。


ダウンキャストにはas?とas!という2通りのやり方があるのだが、それらの違いが分かる様に具体的にコードを実行していこう。


まずはFood型に指定した変数anyFoodにNoodleクラスのインスタンス、Curryクラスのインスタンスを代入する。スーパークラスがどちらもFoodだから代入できるってことでOKかな?

nameプロパティは使えるがspicy,soupプロパティが使えない事を確認する。


Food型の変数に代入した場合でも、その中身がCurryクラスのインスタンスであることに変わりはないが、Curry型の変数にFoodクラスのインスタンスを代入する事はできない。

とてもわかりづらいけど、「FoodクラスのインスタンスanyFoodの中身はCurryクラスのインスタンスである」がそれをCurry型の変数に代入することができないということでOK?

 

さて、こんな時にダウンキャストを使ってサブクラスのインスタンスにキャストをすることができる。まずはas?から。


anyFoodがサブクラスにダウンキャストされてCurry型の変数curryに無事に代入された。そんな内容だ。

ただこれCurry?となっている。これはオプショナルにラップされた状態。

今回はanyFoodをダウンキャストしたらサブクラスのCurryだったからよかったが、違う場合もある。

そういった場合は結果がnilとなって返ってくる、ということだ。

強制的にダウンキャスト

as!を使うと強制的にダウンキャストすることができる。実際に見てみよう。


キャストに成功することが明確にわかっている場合は、アンラップの手間を省くためas!を使う。

失敗したらランタイムエラー(強制終了)となってしまうため、明確じゃなければas?をつかうこと

型のチェック

あるクラスのインスタンスが、サブクラス(又はそのクラス自体)のインスタンスであるかどうか」をチェックできる。

判定結果はBool型(true or false)で受け取ることができる。実際にコードを見てみよう。


ダウンキャストのクラスを引き続き使っている。

anyFoodがNoodle型だったら「今夜はラーメン!」と表示させてCurry型だったら「今夜はカレー!」と表示させるというわけだ。

思いついた

ふと思ったんだが、さきほどの強制的にダウンキャストと組み合わせて使う事出来るのでは?

つまり、「もしサブクラスがAであればAクラスに強制的にダウンキャストする、もしサブクラスがBであればBクラスにダウンキャストする。それ以外だったらダウンキャストしない。」という風なif文を作って、強制的なダウンキャストを安全に行う、みたいな感じ。

なんかそういうのありそうだよね。ここでは真相はわからず。でも出来そう!

といった感じで型のキャストの前半はここで終わり、後半に続くよ。

続き⇒「【Swift奮闘記ep28】型のキャスト後半(Any型とAnyObject型、プロトコルのキャスト)

コメント