Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

Rubyのnilとは?知っておくべきすべてのことを徹底解説

nil……

それは一体何なのでしょうか?

実は、nilはRubyの特別なオブジェクトで、「空」や「値が存在しない」状態を表すために使われます。また、nilは「falsy(偽と評価される)」な値でもあり、条件分岐の中ではfalseと同じように振る舞います。

ここで重要なポイント:

nilオブジェクトはシステム内にたった1つしか存在せず、そのobject_id4(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として扱われます。

数値の0falseとして扱う言語もありますが、Rubyではそうなりません:

if 0
  puts 123
end

# 123

これは「もし0trueなら123を表示する」という意味のコードです。

まとめ

この記事では、nilが「何もないこと」を表すRubyのオブジェクトにすぎないことを学びました。

また、Rubyにおいて「falsy」な値はnilfalseの2つだけで、それ以外はすべて「truthy」であることも理解できましたね。

この記事が役に立ったら、ぜひお気に入りのSNSでシェアしてください!


  1. Bluetooth 5とは?知っておきたい新機能と特徴を徹底解説

    Wi-Fiと同様に、Bluetoothはスマートフォンをはじめとするあらゆるモバイルデバイスに欠かせない技術です。ファイルやデータの転送だけでなく、ワイヤレススピーカーやスポーツ用イヤホンなどの周辺機器との接続にも幅広く活用されています。 Bluetoothはコミュニケーションのあり方を変えただけでなく、多くのデバイスを大型からコンパクトへと進化させました。最新バージョンのBluetooth 5では、従来のバージョンでは実現できなかったさまざまなことが可能になっています。劇的な変革とまでは言えませんが、確かに新しい魅力がいくつも追加されています。それでは、Bluetooth 5がもたらす新機能

  2. PBMファイルとは?正体や開き方・変換方法をわかりやすく解説

    パソコンが身近な存在になって以来、テクノロジーとエンターテインメントの分野は目覚ましい成長を遂げてきました。その中でも最も一般的な娯楽のひとつが、写真をはじめとするメディアコンテンツです。現在の技術では、特定のファイルを開くために対応アプリケーションを探す手間はほとんどありません。しかし、画像やメディアファイルにはそれぞれ異なる種類があり、多様な拡張子が存在することを知っておくことは有益です。そのひとつである「PBM」という拡張子は、ここしばらくユーザーの間で注目を集めています。本記事では、PBMファイルの概要とその扱い方についてわかりやすくご紹介します。 PBMファイルとは? PBMは「P