変数スコープについて
やばい
今更ながら違いを意識した。いままではなんなく無くても動くけどあった方が安心できるんじゃね? みたいな感じで認識していたんだが/(^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:で、あってるかな