2010年7月20日

Objective-Cのnil

諸事情あってiPhoneの開発に手を付けることになりました。四苦八苦しながらObjective-Cを触っているのですが、いかんせんいままでJavaばかりやっていたものでどうにも勝手が悪い。
基本的にCにインタプリタ的なオブジェクトシステムが付与されたランタイム環境で実行される雰囲気ですね。ガベージコレクタなんかも実装されているらしいのだけど、少なくともiPhone環境では使えないらしい。なのでオブジェクトの確保/解放なんかは基本的に自分で面倒をみてやる必要があるのですね。(ある程度補助してくれる機能もついてますが、まぁ根本的にわかってないと使えないので)

で、面白いのが表題にあるnilで基本いわゆるnullオブジェクトのことなのですが、JavaなどではNullオブジェクトにメッセージを送ろうとする(Java言語圏ではメソッドを呼び出す、といいますね)と、基本NullPointerExceptionでありプログラムでしっかりNullチェックをしておく必要がある訳です。ところがこのnilの場合は特に問題なくメッセージを受け付けてしまいます。戻り値のあるセレクタ(Java言語圏ではメソッドにあたる)の場合は結果としてnilを返します。で、プログラム自体は特にエラーになることもなく、何事もなかったように進行します。

メソッドの呼び出しをつなげてメソッドチェーン式でコードを記述するような場面ではJavaの場合途中Nullがかえらないように注意する必要があります。あるいは逐一Nullチェックが必要ですね。これがnilであれば途中でnilになっていても例外などにはならないので、メソッドチェーンの最後でnilになっていないか確認すればよい訳です。

ちょくちょくこの辺の記述で引っかかった経験があるので、これはよいなと思った反面、もちろんnilを想定していないところにnilが入ってきてもエラーになる訳でもなく、想定外の動作をしているのに気づけないといった面もあります。
これが多分、戻り値として結果を返すメソッドだったら結構すぐわかるんじゃないかな、と思うんですよね。作ってる途中に、どこか(画面やファイルなど)に出てくる値になる可能性が高いと思うので。最終的に出てきた値がnilになってて、処理のどこで nilにされたのか追いかける必要はあるかもしれませんが、そのくらいならたいした苦労じゃない気がします。問題は戻り値がないセレクタでしょうね。戻り値がないということは呼び出し側にはわからない状態変化を起こす可能性が高いと思うのですが、nilに対してメッセージを送っていた場合、その結果をどうにかして確認するか、事前にnilチェックを怠らないようにしなければならないということになります。

となると、基本戻り値なしのメソッドは使わない方がいいのかなーという気がします。

オブジェクト指向プログラミングの利点というのは基本的にオブジェクト同士のメッセージのやり取りという基本インフラと、カプセル化(情報へのアクセス権の管理)を行うことで、機能の責務の分断が明確に記述できる点であると思っているのですが、nilが存在することで関連するオブジェクトがその内部状態に配慮しなければならないようであるなら、オブジェクトシステムの利点を阻害しているような気もします。