インスタンス変数とかはselfに依存するという話
@var
が何を指すかって、何を元に判断しているのだろうか。
前提
ローカル変数
「ローカル変数のスコープは、宣言した位置からその変数が宣言されたブロック、メソッド定義、またはクラス/モジュール定義の終りまでです。」*1
class Sample var = 1 end class Sample p var # => undefined local variable or method `var' end
インスタンス変数
インスタンス変数は特定のオブジェクトに属している。
(オブジェクトは変数やメソッドを束ねたもの、と考えてよさそう。)
class Sample @var = 2 end class Sample p @var # => 2 end
本題
「定数やクラス変数、インスタンス変数、グローバル変数は...(中略)...selfを通じて間接的にアクセスされる。」*2
サンプルコードを仕切り直して、まず下準備。
class Sample # `Sample`というClassのインスタンスに@varをもたせる @var = "in Sample" def initialize # `sample`というSampleのインスタンスに@varをもたせる @var = "in an instance of Sample" end end sample = Sample.new class << Sample # `Sampleの特異クラス`というClassのインスタンスに@varをもたせる @var = "in singleton class of Sample" end class << sample # `sampleの特異クラス`というClassのインスタンスに@varをもたせる @var = "in singleton class of sample" end
x_evalメソッドをつかって、いつどの@varが呼ばれるのかをみてみる。
(x_evalしたときのコンテクストについてはこちらでまとめた。)
Sample.class_eval do # self: Sample # klass: Sample p @var # => "in Sample" end Sample.instance_eval do # self: Sample # klass: Sampleの特異クラス p @var # => "in Sample" end sample.instance_eval do # self: sample # klass: sampleの特異クラス p @var # => "in an instance of Sample" end
@varとして呼ばれるのは、その時点でselfによって指し示されるオブジェクトがもつ@varであることが分かった。
雑感
ここ数日evalとかについて考えていたら、Rubyにおいてコードは一見とても立体的に見えるけれど、つまるところ起きているのは単なるプロセスたちの実行で、それをさも「オブジェクトにメッセージを送っている」とか「クラスの中にいる」とか、イリュージョンのように仕立てているだけなのだなあ…と感じた。