すがブロ

sugamasaoのhatenablogだよ

変数スコープについて

やばい

今更ながら違いを意識した。いままではなんなく無くても動くけどあった方が安心できるんじゃね? みたいな感じで認識していたんだが/(^o^)\

モジュール定義の場合に実験

module TestModule
  def get_test
    puts "get_test.id = #{@test.object_id}"
    return @test
  end
  def set_test(test)
    @test = test
    puts "set_test.id = #{@test.object_id}"
  end
end
include TestModule

puts "module"
puts TestModule::get_test
puts TestModule::set_test(100)
puts TestModule::get_test

結果

module
get_test.id = 4
nil # get_test メソッド戻り値
set_test.id = 201
nil # set_test メソッド戻り値
get_test.id = 201
100 # get_test メソッド戻り値

クラスの場合

class TestClass
  def get_test
    puts "get_test.id = #{@test.object_id}"
    return @test
  end
  def set_test(test)
    @test = test
    puts "set_test.id = #{@test.object_id}"
  end
end

puts "class"
obj = TestClass.new
puts obj.get_test
puts obj.set_test(100)
puts obj.get_test

結果

class
get_test.id = 4
nil # get_test メソッド戻り値
set_test.id = 201
nil # set_test メソッド戻り値
get_test.id = 201
100 # get_test メソッド戻り値

結果から考えると

どういう理屈かイマイチ納得感がないけど、メソッドに定義されたインスタンス変数はなぜかインスタンス内のスコープに居座る。インスタンス変数とはそういうものである、という理解で良いのだろうか。
書いていて思ったんだけど、インスタンス変数というくらいだからインスタンス内全体がスコープが発生すると考えると納得できる、かな。
つまり、CとかJavaのレキシカルスコープとは”レキシカル”の定義が違うっつーことなのでしょうか。
http://www.ruby-lang.org/ja/man/html/_CAD1BFF4A4C8C4EABFF4.html
ここの「特定のオブジェクト」っていうのがつまりインスタンスっていうことか。

`@'で始まる変数はインスタンス変数であり、特定のオブジェクトに所属しています。インスタンス変数はそのクラスまたはサブクラスのメソッドから参照できます。初期化されていないインスタンス変数を参照した時の値はnilです。

ということでなんとなく分かってきた。が、その下の一文で意味不明。

クラスにインスタンス変数を定義することが可能ですが、その変数を子クラスの特異メソッドから参照することはできません。

class Foo
  @a= 1
  def self.a
    @a
  end
end

class Baa < Foo
end

p Foo.a  # 1
p Baa.a  # nil

self.a でメソッドを定義しているということはいわゆる static メソッドということなはず。そこからはアクセスできる。けれど、

def a
  @a
end

のような定義に変えて、 Foo.new.a とかやると nil が返る。これは最初に上の方で試した結果と同じことだろう(あくまでインスタンス変数はメソッド内で定義した場合だから*1)。
うーん、動きとしてはわかるのだけど、理屈がよくわからん。これだったら普通にクラス変数で良くね? クラス変数として定義するとサブクラスからでも参照できちゃうから、それを嫌ってこういう動きになってるってことなのか。
ぶっちゃけマニュアル見てもよくわからない。
あと、マニュアルの記述にある特定のオブジェクトとかインスタンスとかが、どういう状態を指しているか、というのをきちんと説明してあげると理解しやすいんだろうけどなぁ。

ここまできてようやく気がついた

こんなところが理解できないのはおれが低能すぎるのか/(^o^)\

*1:で、あってるかな