Swift 「!」と「?」について

初めに

 swift を始めた頃、「?」や「!」という記号が登場している場面はよくありましたが、気にしなくても、swift自身が勝手に直してくれるので、無視していました。しかし、今後、学びを進める上で、かなり重要な部分になるのではないかと思い、ここに調べたことを残していきたいと思います。

「?」「!」とは?

これはオプショナル型と言われる型の一つだそうです。宣言の時は次のようにできます。

f:id:kouki-matsuura:20200606001944p:plain

変数aでオプショナルInt型といいます。これをすれば何がいいのか、と言うと、nilという特別な値が扱うことができます。普通の型ではこの値を扱うことができません。まずは、nilを持っていることを確かめるために次のようにaの中身を表示しました。

f:id:kouki-matsuura:20200606004236p:plain f:id:kouki-matsuura:20200606004249p:plain

では、次にオプショナルInt型の値をInt型の値と組み合わせてみます。

f:id:kouki-matsuura:20200606005103p:plain

bにa+1の値を代入すると、エラーが起こりました。エラーの内容はオプショナルInt型をInt型にするためにアンラップをしてくださいというものでした。

f:id:kouki-matsuura:20200606005124p:plain

アンラップというのはオプショナル型の変数に「!」をつけることです。つまり、「!」をつけることでオプショナル型を普通の型として扱えるということです。

「!」をつけてもう一度計算してみます。

f:id:kouki-matsuura:20200606005714p:plain

エラーが消えました!

「?」でnilを扱え、「!」で普通の型に戻すことができるということがわかりました。

オプショナル型の利点

「?」と「!」がどういうものかの基礎はわかったのですが、いまいち、「?」が何のために存在しているのか分からなくなりました。nilのようなものを使わなくても、Javaなどで使われているnullを使えば、普通の型だけでプログラムが書けると思ったのです。

疑問がどんどん浮かんできたので、調べてきました。

調べた結果、オプショナル型という制約がつくおかげでアプリケーションでのエラーが起きることを防ぐことができます。

nilはnullと同じように、アプリケーション内で参照してしまうと、落ちてしまいます。

しかし、nilはnullと違い、オプショナル型の変数でしか扱えません。しっかりとしたルールがあるため、nilかどうかチェックを省くことができます。

アプリケーションでのエラーを未然に防ぐことができることが最大の利点と言えるのかもしれません。

guard文

先ほどはオプショナル型の利点を紹介しましたが、絶対に大丈夫ということはありません。想定外の状況が発生しうることもあります。

ここでいう想定外の状況というのが、アプリケーションが落ちてしまう原因の一つの「nilの参照」です。このような状況を回避するための構文としてguard文があります。

ここでは、まず僕が作った簡単なプログラムと実行結果を貼らせていただきます。

f:id:kouki-matsuura:20200606011835p:plain f:id:kouki-matsuura:20200606011913p:plain

guard文の書き方として、”guard 条件 else { 処理A }”となってます。

条件を成立しない時に処理Aを行われることになっています。なので、配列nums[5]を参照された時に「nilです」と表示されるわけです。これで少なくとも、突然、アプリケーションが落ちるということは回避されます。

nil合体演算子

これも、nilによる、アプリケーションが落ちる現象を少し防げる工夫が施されているものです。具体的に説明すると、ある値がnilだった時に、別に指定しておいた値を代わりに処理に用いるというものです。

プログラムを作ってみました。先ほどと同じnums配列をfor文で回し、1つ1つ、関数exampleに入れています。exampleでは、引数であるnumがnilだった場合、999をansに入れ、通常の数の場合はそのまま入れるようにしました。実行結果は右下になります。普通の数である0~4は正しく表示されており、nilだったはずの要素が999になっていることが確認できました。

nil合体演算子がどういうものか理解できたと思います。

f:id:kouki-matsuura:20200609050050p:plain f:id:kouki-matsuura:20200609050107p:plain

有値オプショナル型

通常のオプショナル型では、nilが入っている可能性もあるため、guard文やnil合体演算子で処理する必要があったが、有値オプショナル型はそれらの処理を施さずに、変数に入れることができます。また、有値オプショナル型は宣言の際に「!」をつけることで宣言できます。

有値オプショナル型がよく用いられるのはUI部品だと思います。画面の上に置いたUIとプログラムをつなげた時に自動で宣言されるものも有値オプショナル型です。

f:id:kouki-matsuura:20200610060128p:plain

これが自動的にされることにより、僕たちは毎回、UIごとにnilか否かの判断をする必要がなくなります。UI部品は全て初めはnilが代入されていますが、アプリケーションを立ち上げると同時に値が勝手に格納されているので心配することもありません。とても便利なものです!

終わりに

どうだったでしょうか。今までモヤモヤしていたものが少しは晴れたような気がします。オプショナル型とは、swiftを触っている限り、ついてくるものなので今の間に学べてよかったと感じています。

次の記事では、新たなアプリを作成していこうかなと考えています。

見ていただきありがとうございました!