Rubyのnilとは?なぜnilを使うのか、その理由をわかりやすく解説
ある日、友人とRubyのコードについて話していたとき、「メソッドの戻り値」というテーマが話題に上がりました。
そして当然のように、nilの話も登場します。
その日の夜、ベッドに入って眠りにつこうとしていたとき、ふと「そもそも、なぜ私たちはnilを使うのだろう?」と考え始めました。
これは良い記事のネタになると思い、翌日にこの記事を書くことにしました。この記事を通じて、何か新しい発見や学びがあると嬉しいです!
戻り値と期待される動作について
selectのようなメソッドを呼び出すと、必ず配列(Array)が返ってきます。
たとえ何も選択する要素がなくても、です。
例:
[1,2,3].select {}
# []
[1,2,3].select(&:even?)
# [2]
では、なぜこれが重要なのでしょうか?
良い質問ですね!
常に配列が返ってくることが保証されていれば、実際に扱っているのが配列かどうかを確認せずに、配列のメソッド(size、empty?、pushなど)を安心して呼び出せるからです。
これはとても良いことです。なぜなら、クラスのチェックは高い結合度(カップリング)を招くからです。
より柔軟なコードを書きたいのであれば、「これは何のクラスか?」という確認はできるだけ避けるべきです。
単一の値を返す場合
さて、ではfindのように、1つの値だけを返すメソッドの場合はどうでしょうか?
要素が見つかれば、問題なく動作します。
[1,2,3].find { |n| n == 2 }
# 2
しかし、マッチする要素が見つからなかった場合はどうでしょう? findは何かを返さなければなりません。falseを返すことも可能ですが、戻り値に対してメソッドを呼び出そうとすると、例外が発生してしまいます。
ここで登場するのがnilです。私たちがnilを使うのは、汎用的なNullオブジェクトとして最も近い存在だからなのです。
前回のnilに関する記事で紹介したように、nilは実はクラスであり、to_i、to_s、to_aといったメソッドを持っています。
このおかげで、Array()やString()のようなメソッドを使って、オブジェクトをこれらの型へ変換できます。
例:
String(123) # "123" String(nil) # "" Array(nil) # []
これは文字列補間(インターポレーション)でも活用されています。
"abc#{nil}dfg"
文字列補間では、補間ブロック内の式の評価結果に対してto_sが呼び出されます。つまり、#{1 + 1}と書けば、内部的には2.to_sが実行されるということです。
nilが問題になるケース
しかし、nilには予期しない場面で現れたときに問題が発生します。「fooメソッドに応答するオブジェクト」だと思っていたのに、実際はnilだった——そんなとき、恐ろしいNoMethodError例外が発生します。
このような場合には、Null Objectパターンを実装するのが有効です。また、デフォルト値を指定できるfetchメソッドを使う方法や、デフォルト値を設定することが意味をなさない場合には明示的に例外を発生させるという解決策もあります。
まとめ
この記事では、なぜ私たちがnilを使うのか、nilに対するメソッド呼び出しによる例外をどう回避するか、そしてより自信を持って書けるコードの書き方を学びました。
ぜひ自分のコードを見直して、型チェックを行っている箇所(is_a? / kind_of? / ===など)を探してみてください。今日学んだことを活かせば、そのコードをもっと改善できるはずです。
-
HTMLページでheadタグを使う理由とは?基本的な使い方を解説
<head>タグは、HTMLページ内のすべてのヘッダー要素を格納するためのコンテナです。画面上に直接表示される本文(body)とは異なり、文書自体に関する情報=メタデータを定義する重要な役割を担っています。 <head>…</head>タグの追加方法はとても簡単です。この中には、文書のタイトル(<title>)、メタ情報(<meta>)、スタイルの定義(<style>や<link>)、スクリプトの読み込み(<script>)などを記述します。 特に覚えておきたいのは、<title>…&l
-
HTMLドキュメントにDOCTYPE宣言が必要な理由とは?種類と書き方を徹底解説
HTMLにおける<!DOCTYPE>タグは、そのドキュメントがどのバージョンのHTMLで記述されているかをブラウザに伝えるためのものです。これを「文書型宣言」と呼びます。 <!DOCTYPE>宣言は、HTMLドキュメント内で最初に現れる要素であり、必ず<html>タグよりも前に記述します。また、<!DOCTYPE>タグには終了タグが存在しない点にも注意しましょう。 DOCTYPE宣言を正しく記述することで、ブラウザは標準準拠モード(スタンダードモード)でページをレンダリングします。逆に宣言がない場合、ブラウザが互換モード(クワークスモード)で動作