Rubyのnilとは?知っておくべきすべてのことを徹底解説
nil……
それは一体何なのでしょうか?
実は、nilはRubyの特別なオブジェクトで、「空」や「値が存在しない」状態を表すために使われます。また、nilは「falsy(偽と評価される)」な値でもあり、条件分岐の中ではfalseと同じように振る舞います。
ここで重要なポイント:
nilオブジェクトはシステム内にたった1つしか存在せず、そのobject_idは4(64ビット版のRubyでは8)です。これこそが、nilが特別な存在である理由の1つです。
nil.object_id # 4
それでは、さらに深く掘り下げていきましょう!
nilはどこからやってくるのか?
多くのメソッドは、結果としてnilを返すことがあります。
これは「値を要求したのに、その値が利用できない」場合に起こります。
具体例:
- 商品が見つからない
- 配列のインデックスが範囲外
- ハッシュにキーが存在しない
これを示すコードがこちらです:
arr = [1,2,3] arr[5] # nil
私たちはメソッドが有効な値を返してくれると期待しているため、nilが返ってくるとさまざまな問題が発生しがちです。
たとえば、次のようなNoMethodError例外が発生します:
arr[5].size # NoMethodError: undefined method 'size' for nil:NilClass
このエラーを回避するには、メソッドを呼び出す前に値がnilでないかを確認する必要があります。
Rubyでnilを判定する方法
「undefined method for nil:NilClass」というエラーを出したくないなら、次の方法を試してみましょう。
nilでない場合にのみメソッドを呼び出す:
if array[5] && array[5].size # 何か処理をする... end
こうした書き方をシンプルにするため、Ruby 2.3では「安全なナビゲーション演算子」(&.)が導入されました。
例:
if arr[5]&.size # 何か処理をする... end
nilを判定するもう1つの方法が、nil?メソッドを使うことです:
if @bacon.nil? # ... end
また、Railsであればblank?メソッドを使うという選択肢もあります。
扱うオブジェクトの種類によっては、nilチェック自体を完全に回避できるテクニックもいくつかあります。
たとえば、HashやArrayオブジェクトにはfetchメソッドが使えます。
また、自作クラスで「nilの代わりにデフォルト値を返したい」場合は、「Null Objectパターン」を活用するのも良いでしょう。
nilが潜んでいるその他の場所
未定義のインスタンス変数はnilを返すという点に注意してください。
@foo # nil
インスタンス変数の名前をタイプミスしていたり、初期化し忘れていたりすると、思わぬnilに遭遇することがあります。気をつけましょう!
もう1つnilが現れるのが、putsメソッドとprintメソッドです。
この2つのメソッドは必ずnilを返します。
これを取り上げるのは、実際に受講生が次のようなコードを書いてしまうのを見たことがあるからです:
numbers = [1,2,3].map { |n| puts n * 2 }
この結果、numbersは[nil, nil, nil]になってしまいます。解決策は、ブロックの中からputsを取り除くことです。
NilClassを理解する
Rubyの他のオブジェクトと同じように、nilにも一連のメソッドが定義されています。
以下はRubiniusのクラス定義です:
class NilClass
def to_s
""
end
def inspect
"nil"
end
def nil?
true
end
def to_a
[]
end
def to_f
0.0
end
def to_i
0
end
def to_c
Complex(0)
end
def to_h
{}
end
end
注目すべきは、これらのto_○○系メソッドがすべて「空の値」を返している点です(数値なら0)。
空のハッシュ、空の文字列、空の配列……
こうなっているのは、nilが「何もないこと」を表すために使われているからです。
Null Objectパターン
nilについて語るなら、Null Objectパターンに触れないわけにはいきません。
Sandi Metzは、素晴らしい講演「Nothing is Something」の中で、nilは「何もない」ことを意味する一方で、より具体的な意味を持たせられると指摘しています。
たとえば、商品を検索するメソッドを書いていて、商品が見つからない場合にデフォルトの商品を返したいとしましょう。
その場合、次のような「null商品」を返せばOKです:
class MissingProduct
def name
"Product not found"
end
end
こうすると、実際の商品オブジェクトとnull商品が混在する配列があっても、すべての商品がnameメソッドを持つことになります。つまり、NoMethodError例外が発生しなくなるのです。
ヒント: オブジェクトの型をチェックすることなく、すべてのオブジェクトを同じように扱えるなら、それはポリモーフィズム(多態性)を活用できている証拠です。
この種のオブジェクトはビュー(プレゼンテーション層)では非常に便利ですが、コントローラでは注意が必要です。コントローラでは、対象が見つからなかった場合にアラートを表示したりリダイレクトしたりと、別の処理を行いたいことが多いからです。
真偽値としてのnil(truthiness)
nilについて知っておくべきもう1つのポイントは、false(これもオブジェクトです)と並んで、nilだけが「falsy(偽と評価される)」な値だという点です。
Rubyでは、それ以外のすべての値はブール値のコンテキストでtrueとして扱われます。
数値の0をfalseとして扱う言語もありますが、Rubyではそうなりません:
if 0 puts 123 end # 123
これは「もし0がtrueなら123を表示する」という意味のコードです。
まとめ
この記事では、nilが「何もないこと」を表すRubyのオブジェクトにすぎないことを学びました。
また、Rubyにおいて「falsy」な値はnilとfalseの2つだけで、それ以外はすべて「truthy」であることも理解できましたね。
この記事が役に立ったら、ぜひお気に入りのSNSでシェアしてください!
-
Bluetooth 5とは?知っておきたい新機能と特徴を徹底解説
Wi-Fiと同様に、Bluetoothはスマートフォンをはじめとするあらゆるモバイルデバイスに欠かせない技術です。ファイルやデータの転送だけでなく、ワイヤレススピーカーやスポーツ用イヤホンなどの周辺機器との接続にも幅広く活用されています。 Bluetoothはコミュニケーションのあり方を変えただけでなく、多くのデバイスを大型からコンパクトへと進化させました。最新バージョンのBluetooth 5では、従来のバージョンでは実現できなかったさまざまなことが可能になっています。劇的な変革とまでは言えませんが、確かに新しい魅力がいくつも追加されています。それでは、Bluetooth 5がもたらす新機能
-
PBMファイルとは?正体や開き方・変換方法をわかりやすく解説
パソコンが身近な存在になって以来、テクノロジーとエンターテインメントの分野は目覚ましい成長を遂げてきました。その中でも最も一般的な娯楽のひとつが、写真をはじめとするメディアコンテンツです。現在の技術では、特定のファイルを開くために対応アプリケーションを探す手間はほとんどありません。しかし、画像やメディアファイルにはそれぞれ異なる種類があり、多様な拡張子が存在することを知っておくことは有益です。そのひとつである「PBM」という拡張子は、ここしばらくユーザーの間で注目を集めています。本記事では、PBMファイルの概要とその扱い方についてわかりやすくご紹介します。 PBMファイルとは? PBMは「P