null(nil)に対して厳格なSwiftでの注意点

過去のブログのアーカイブ
この記事は前身のブログのアーカイブを引き継いだものです. 画像が正しく表示できないなど,コンテンツの表示に問題がある恐れがあります.

他の言語からSwiftを学ぶとnilに対する厳格さがちょっと気になる。値型や参照型とか関係なしにnilの可能性があるものにはきちんと明記してあげる必要があります。

「C#プログラマのための〜」カテゴリなのでC#コードと比較していますが、多分C++とかでも同じだと思う。

nil(null)の可能性があるものには?を

型の指定の際に、nilの可能性があるものには型名の後ろに?を付けてあげればなんでもnil許容型になる。これはC#でも同じかな。ただ型のタイプがなんであれ、nilを許容するには?をつける必要がある。?がないものにnilが設定されることはありえない

Stringの場合

String str = "Hello world";
str = null; // もちろん大丈夫
str = "hogehoge"; // もちろんこれも
var str:String = "Hello world!"
str = nil        // これはダメ
str = "hogehoge" // これはOK
var str2:String? = "Hello World"
str2 = nil         // 問題なし
str2. = "hogehoge" // これも

C#でもString型は参照型っぽい特性も持ってるのでnullを代入することは可能。もちろん?を付ける必要もない。

intの場合

ただしC#の場合、int型は値型なのでnullを代入することはできない。もとから?がないとnilが代入できないSwiftとここでは同じ。

int val = 123;
val = null; // これはダメ
int? val2 = 123
val2 = null; // これはOK
var val:Int = 123
val = nil // これダメ
val val2:Int? = 123
val2 = nil // これOK
スクリーンショット 2017-03-08 17.38.37

nil許容型を扱い上での注意

私がなかんかなれなかったポイントなのですが、nil許容型のオブジェクトを扱う際、いちいち?を付ける必要があるのだ。これが面倒なら最初から許容型ではない普通の型に変換してから使って上げる必要がある。
また、戻り値がnilだとまずい場合、この変数の中身がnilじゃないことを保証できるならば強制ダウンキャストをしてから使って上げる必要がある

var val:Int? = 123
print(items: val? + 456)
// もしもprintメソッドのitems引数にnilを指定するのがダメな場合、
// valの中身がnilではないと断定できるならば強制ダウンキャストをする
print(items: val! + 456)

これがswiftの面倒なところじゃないかなと思う。もちろんそのオブジェクトのメンバーを呼ぶ場合も必要になる。

var val:Int? = 123
val?.toIntMax()

この仕様は正直面倒だが安全だと思う。最も、エラーが起きたらエラーメッセージが出るだけで続行可能なプログラミング言語ならともかく、例外が発生するとアプリが落ちるんだから、できるだけ例外が発生する要因をなくすのが一番だとは思う。

正直な感想

C#とかJavaじゃいわゆる「ぬるぽ」が発生しないのはいいことなのかな。確かにぬるぽバグはプログラミングの例外の中で一番発生頻度は高いと思う。
例外が発生しづらい言語というのは、コードを書く上での制約が満載ってことなんだなーって。