Ruby では、初期化されていない、または存在しない変数のほとんどが に評価されnil
ます。これは、ローカル変数、インスタンス変数、およびグローバル変数に当てはまります。
defined? foo #=> nil
local_variables #=> []
if false
foo = 42
end
defined? foo #=> 'local-variable'
local_variables #=> [:foo]
foo #=> nil
foo.nil? #=> true
defined? @bar #=> nil
instance_variables #=> []
@bar #=> nil
@bar.nil? #=> true
# warning: instance variable @bar not initialized
defined? $baz #=> nil
$baz #=> nil
# warning: global variable `$baz' not initialized
$baz.nil? #=> true
# warning: global variable `$baz' not initialized
ただし、クラス階層の変数と定数には当てはまりません。
defined? @@wah #=> nil
@@wah
# NameError: uninitialized class variable @@wah in Object
defined? QUUX #=> nil
QUUX
# NameError: uninitialized constant Object::QUUX
これは赤いニシンです:
defined? fnord #=> nil
local_variables #=> []
fnord
# NameError: undefined local variable or method `fnord' for main:Object
ここでエラーが発生する理由は、初期化されたローカル変数が に評価されないからではなく、あいまいなためです:デフォルトの受信者 (つまり と同等)に送信される引数なしのメッセージか、またはへのアクセスのいずれかです。ローカル変数。nil
fnord
self.fnord()
fnord
それを明確にするために、受信者または引数リスト (空の場合でも) を追加して、それがメッセージ送信であることを Ruby に伝える必要があります。
self.fnord
# NoMethodError: undefined method `fnord' for main:Object
fnord()
# NoMethodError: undefined method `fnord' for main:Object
または、使用前にパーサー(エバリュエーターではなく) が代入を解析 (実行ではなく) して、それがローカル変数であることを Ruby に伝えるようにします。
if false
fnord = 42
end
fnord #=> nil
インスタンス変数の扱いがローカル変数やクラス変数と異なるのはなぜですか?
そうではありません。ローカル変数と同じように扱われます。クラス階層変数は異なる動作をする変数であり、ローカル変数、インスタンス変数、およびグローバル変数はすべて同じ動作をします。
他の理由はありますか...クラス変数もそのように動作することはできませんか?
知らない。インスタンス変数の場合は非常に便利です。たとえば、インスタンス変数がクラス定義で宣言され、クラスのすべてのインスタンスに対して常に存在する Java とは異なり、Ruby ではインスタンス変数はどこにも宣言されないためです。それらは、割り当てられるとすぐに、魔法のように出現します。インスタンス変数の存在が保証されているとは限らないため、インスタンス変数を使用するメソッドを作成すると、例外がスローされた場合に苦労します。
クラス階層変数が異なる理由はわかりません。たぶん、誰もそれらを使用していないか、一般的にクラス本体で初期化される傾向があり、初期化されていない場合は単にアクセスされないためです。