iPhoneのゲームアプリを開発していて今まで意識したことのなかったダウンキャストに触れる機会があった。
`SKPhysicsContactDelegateのdidBeginを使って接触判定を実装しているのだが、何と何が接触したかを判別する必要がある。
今開発しているゲームでは、カエルやハエなどの複数の敵が登場する。
プレイヤーの発射した弾が敵にヒットした場合、敵は死ぬようにしたい。
しかし、didBeginの中では、弾が接触したノードがカエルなのかハエなのか(何のクラスか)が分かっていない。
そこでasを使ったダウンキャストを実装し、弾が当たったのがカエルなのかハエなのかを判別する。
Optional型をダウンキャストする場合には二通りの書き方がある。
1つ目がas? Typeを使う方法。
if let frog = two.node as? Frog{ : }
2つ目がas! Type?を使う方法だ。
if let frog = two.node as! Frog?{ : }
この2つの違いは何だろうか。
1つ目のasは「ノードがカエルだったらダウンキャストする。」という意味になる。
つまり、接触したものがカエル以外であっても、if文の中身が実行されないだけでエラーは発生しない。
それに対して2つ目のas!は、「ノードが必ずカエルであるとみなして、ダウンキャストする」という意味になる。
だから、もし接触したのがカエル以外のノードであった場合にはエラーが発生する。
どちらを使った方が良いのか?
ケースバイケースである。
今回のように、ゲームプレイ中は弾がカエルに当たるのかハエに当たるのか分からないような場合には、1つ目の方法で実装した方が良い。
逆に、ダウンキャストする先が決定しているのであれば、2つ目の方法を用いてダウンキャストした方がバグを発見しやすいと思う。