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

Rubyで変数が定義されているか確認する方法!defined?の使い方と注意点を徹底解説

Rubyには、変数が定義されているかどうかを手軽に確認できるdefined?というキーワードが用意されています。

変数が存在する場合は、その種類が文字列として返されます

apple = 1

defined?(apple)
# => "local-variable"

存在しない場合は、nilが返されます

defined?(bacon)
# => nil

これはJavaScriptのtypeof演算子に近い働きをするものです。ただし、オブジェクトのクラスそのものを知りたいときは、defined?ではなくclassメソッドを使いましょう。

defined?には、いくつか覚えておきたい特徴があります。

  • defined?メソッドではなく「キーワード」であること
  • 名前の末尾に?が付くメソッドはtruefalseを返すのがRubyの慣習ですが、defined?はこの慣習に従わない数少ない例外であること
  • 値がnilの変数と、一度も代入されたことのない未定義の変数を区別できること

こうした特異な性質を持つキーワードだからこそ、正しく理解して使うことが重要です。

defined?の落とし穴と、より良い代替手段

defined?は便利な一方で、注意すべき問題点もあります。

その原因は演算子の優先順位が極めて低いことです。

たとえば、次のように書いたとしましょう。

defined? orange && orange.size

この結果は"expression"となり、意図した動作になりません。

なぜなら、orange && orange.sizeの全体がdefined?への引数だと解釈されてしまうからです。

正しく評価させるには、次のように括弧で囲みます。

defined?(orange) && orange.size

さらにRubyには、変数が定義済みかどうかを調べる別の方法も用意されています。

ローカル変数の場合:

local_variables.include?(:orange)

インスタンス変数の場合:

instance_variable_defined?("@food")

とはいえ、これらを使いたくなる場面は実務ではほとんどありません。

ローカル変数が見つからないケースの99%は、単純なタイポ(打ち間違い)か変数の宣言忘れです。まずはコードを見直すのが先でしょう。

では、インスタンス変数はどう扱えばいいのでしょうか?

未定義のインスタンス変数は常にnilを返すため、定義チェックよりもnilチェックを行うのが基本です。

ここで活躍するのが「セーフナビゲーション演算子」(&.)です(Ruby 2.3以降で使用可能)。レシーバがnilでない場合にだけメソッドを呼び出してくれます。

使用例:

if @user&.country == "Spain"
  # ...
end

これは次のコードと同等です:

if @user && @user.country == "Spain"
  # ...
end

これらの方法はdefined?ほど万能ではありませんが、挙動が予測しやすく、エラーも起きにくいという大きなメリットがあります。

メソッドが定義されているか確認する

defined?はメソッドの存在確認にも使えますが、実用性はそれほど高くありません。

:

defined?(puts)
# => "method"

defined?はあくまでキーワードであってメソッドではないため、オブジェクトに対しては呼び出せません。

たとえば、次のような書き方はエラーになります:

[].defined?(:size)
# NoMethodError: undefined method `defined?' for []:Array

オブジェクトが特定のメソッドに応答するかどうかを知りたい場合は、respond_to?メソッドを使いましょう。

使い方は次の通りです:

[].respond_to?(:size)
# => true

[].respond_to?(:orange)
# => false

クラスが存在するか確認する

defined?を使えば、クラス(定数)の存在確認もできます。

:

defined?(Object)
# => "constant"

defined?(A)
# => nil

ただし、より確実なのはconst_defined?メソッドを使う方法です。

次のように記述します:

Object.const_defined?(:String)
# => true

Object.const_defined?(:A)
# => false

まとめ

この記事では、指定した変数・メソッド・クラスが存在するかどうかを確認する方法を紹介しました。

変数を扱う場面では、「定義されているかどうか」よりも「nilかどうか」をチェックすることが大半です。さらに堅牢なコードにしたいなら、to_ito_sなどの変換メソッドを使って、変数をあらかじめ既知のクラスへ変換しておくのがおすすめです。

この記事がお役に立てたなら、ぜひシェアしていただけると嬉しいです。より多くの人に届きますように!

  1. Rubyで環境変数を使う方法|ENVオブジェクトの操作から設定・Rails credentialsまで徹底解説

    環境変数とは、次のような「キーと値」のペアとして表されるデータのことです。 KEY=VALUE この変数は、パソコン上で動くすべてのプログラム間で設定情報(コンフィグ)を共有するために使われています。 だからこそ、環境変数がどのような仕組みで動作し、Rubyプログラムから特殊な ENV オブジェクトを使ってどうアクセスするのかを学んでおくことが大切なのです。 環境変数の活用例 デフォルトエディターの設定 Rubyにgemの保存場所を伝える(GEM_PATH / GEM_HOME) APIキーをGitリポジトリにコミットすることなくアプリケーションへ渡す OSがバイナリファイル(Windo

  2. Rubyのマトリックス(行列)とは?配列・Matrixクラス・Daruを使いこなす完全ガイド

    マトリックス(行列)とは、表計算ソフトのようなデータを格納・操作するための2次元(2D)配列のことです。 マトリックスが活躍する場面: チェスやオセロなど、テーブルゲームの盤面を表現する 統計処理やデータ分析を行う グラフやプロットを生成する マトリックスは非常に強力なデータ構造なので、その使い方をマスターしておくと開発の幅が大きく広がります。この記事では、Rubyでマトリックスを扱う3つの方法——配列、Matrixクラス、そしてDaru gem——を順番に解説していきます。 Rubyでマトリックスを作成する方法 最もシンプルな方法は、配列の入れ子(ネスト)を使ってマトリックスを作ることで