実行コンテキストとは
実行コンテキストとは、プログラムの実行時の文脈や環境のことを言います。
その実行時にどのような変数やメソッドが定義されていて、スコープはどうなっているのかなどです。
Rubyの場合、プログラムを実行するとmainというオブジェクトが生成され、これがトップレベル、グローバルの実行コンテキストになります。(※ main
はObject
クラスのインスタンス)
したがって、Rubyにおいてプログラムは、mainというグローバルコンテキストの中で実行されるということになります。
irb
を起動してselfと入力すると、mainが返ってきますが、これはmainというコンテキストで実行されるということです。
irb(main):001:0> self
=> main
クラス定義やインスタンスを作成すると、実行コンテキストが作成されます。
Binding
RubyではBindingクラスによって、上記で説明した実行コンテキストをオブジェクトとして持つことができます。
bindingメソッドを実行するとその実行コンテキストのオブジェクトを生成します。
irb(main):001:0> b = binding
=> #<Binding:0x00000001008ba668>
class定義やインスタンス生成によって作成された実行コンテキストも以下のようにbindingメソッドによってオブジェクト化することができます。
class Hoge
def self.class_binding
binding
end
def instance_binding
binding
end
end
cb = Hoge.class_binding
ib = Hoge.new.instance_binding
puts cb, cb.receiver
# => #<Binding:0x0000000102e60d40>
# => Hoge
puts ib, ib.receiver
# => #<Binding:0x0000000102e60b60>
# => #<Hoge:0x0000000102e60ca0>
トップレベル、グローバルの実行コンテキストのオブジェクトは定数になっていて、TOPLEVEL_BINDINGで参照することができます。
irb(main):001:0> b = TOPLEVEL_BINDING
=> #<Binding:0x0000000109ddcca0>
eval
evalメソッドでは、このBindingオブジェクトを指定することによって、評価のコンテキストを変えることができます。
@x = 'global'
class Hoge
def initialize(x)
@x = x
end
def self_binding
binding
end
end
hoge = Hoge.new('instance')
instance_binding = hoge.self_binding
eval("puts @x", TOPLEVEL_BINDING)
# => global
eval("puts @x", instance_binding)
# => instance
1つ目のeval
は第2引数にTOPLEVEL_BINDING
を渡しているため、第1引数のscriptをTOPLEVEL_BINDING
の実行コンテキストで評価しています。
そのため、インスタンス変数@x
は、グローバルコンテキストのインスタンス変数を参照します。
2つ目のeval
は第2引数にインスタンス生成によって生成された実行コンテキストのオブジェクトを渡しているため、その実行コンテキストで評価されています。この場合、生成されたインスタンスのインスタンス変数@x
を参照します。
参考記事