13

Ruby 1.8.7 と 1.9.2 で同じ:

$ irb

ruby-1.8.7-p302 > foo.nil?
NameError: undefined local variable or method `foo' for #<Object:0x3794c>
    from (irb):1

ruby-1.8.7-p302 > @bar.nil?
 => true 

ruby-1.8.7-p302 > @@wah.nil?
NameError: uninitialized class variable @@wah in Object
    from (irb):3

インスタンス変数の扱いがローカル変数やクラス変数と異なるのはなぜですか?

4

1 に答える 1

17

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

ここでエラーが発生する理由は、初期化されたローカル変数が に評価されないからではなく、あいまいなためです:デフォルトの受信者 (つまり と同等)に送信される引数なしのメッセージか、またはへのアクセスのいずれかです。ローカル変数。nilfnordself.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 ではインスタンス変数はどこにも宣言されないためです。それらは、割り当てられるとすぐに、魔法のように出現します。インスタンス変数の存在が保証されているとは限らないため、インスタンス変数を使用するメソッドを作成すると、例外がスローされた場合に苦労します。

クラス階層変数が異なる理由はわかりません。たぶん、誰もそれらを使用していないか、一般的にクラス本体で初期化される傾向があり、初期化されていない場合は単にアクセスされないためです。

于 2010-10-26T11:37:00.080 に答える