类 Binding
Binding
类对象封装了代码中某个特定位置的执行上下文,并保留此上下文以供将来使用。在此上下文中可以访问的变量、方法、self
的值以及可能存在的迭代器块都将被保留。Binding
对象可以使用 Kernel#binding
创建,并提供给 Kernel#set_trace_func
的回调函数和 TracePoint
的实例。
这些绑定对象可以作为 Kernel#eval
方法的第二个参数传递,为评估建立一个环境。
class Demo def initialize(n) @secret = n end def get_binding binding end end k1 = Demo.new(99) b1 = k1.get_binding k2 = Demo.new(-3) b2 = k2.get_binding eval("@secret", b1) #=> 99 eval("@secret", b2) #=> -3 eval("@secret") #=> nil
Binding
对象没有特定于类的任何方法。
公共实例方法
eval(string [, filename [,lineno]]) → obj 点击切换源代码
在绑定的上下文中评估string 中的 Ruby 表达式。如果提供了可选的filename 和lineno 参数,它们将在报告语法错误时使用。
def get_binding(param) binding end b = get_binding("hello") b.eval("param") #=> "hello"
static VALUE bind_eval(int argc, VALUE *argv, VALUE bindval) { VALUE args[4]; rb_scan_args(argc, argv, "12", &args[0], &args[2], &args[3]); args[1] = bindval; return rb_f_eval(argc+1, args, Qnil /* self will be searched in eval */); }
local_variable_defined?(symbol) → obj 点击切换源代码
如果存在局部变量 symbol
,则返回 true
。
def foo a = 1 binding.local_variable_defined?(:a) #=> true binding.local_variable_defined?(:b) #=> false end
此方法是以下代码的简短版本
binding.eval("defined?(#{symbol}) == 'local-variable'")
static VALUE bind_local_variable_defined_p(VALUE bindval, VALUE sym) { ID lid = check_local_id(bindval, &sym); const rb_binding_t *bind; const rb_env_t *env; if (!lid) return Qfalse; GetBindingPtr(bindval, bind); env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)); return RBOOL(get_local_variable_ptr(&env, lid)); }
local_variable_get(symbol) → obj 点击切换源代码
返回局部变量 symbol
的值。
def foo a = 1 binding.local_variable_get(:a) #=> 1 binding.local_variable_get(:b) #=> NameError end
此方法是以下代码的简短版本
binding.eval("#{symbol}")
static VALUE bind_local_variable_get(VALUE bindval, VALUE sym) { ID lid = check_local_id(bindval, &sym); const rb_binding_t *bind; const VALUE *ptr; const rb_env_t *env; if (!lid) goto undefined; GetBindingPtr(bindval, bind); env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)); if ((ptr = get_local_variable_ptr(&env, lid)) != NULL) { return *ptr; } sym = ID2SYM(lid); undefined: rb_name_err_raise("local variable `%1$s' is not defined for %2$s", bindval, sym); UNREACHABLE_RETURN(Qundef); }
local_variable_set(symbol, obj) → obj 点击切换源代码
将名为 symbol
的局部变量设置为 obj
。
def foo a = 1 bind = binding bind.local_variable_set(:a, 2) # set existing local variable `a' bind.local_variable_set(:b, 3) # create new local variable `b' # `b' exists only in binding p bind.local_variable_get(:a) #=> 2 p bind.local_variable_get(:b) #=> 3 p a #=> 2 p b #=> NameError end
此方法的行为类似于以下代码
binding.eval("#{symbol} = #{obj}")
如果 obj
可以用 Ruby 代码转储。
static VALUE bind_local_variable_set(VALUE bindval, VALUE sym, VALUE val) { ID lid = check_local_id(bindval, &sym); rb_binding_t *bind; const VALUE *ptr; const rb_env_t *env; if (!lid) lid = rb_intern_str(sym); GetBindingPtr(bindval, bind); env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)); if ((ptr = get_local_variable_ptr(&env, lid)) == NULL) { /* not found. create new env */ ptr = rb_binding_add_dynavars(bindval, bind, 1, &lid); env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)); } #if YJIT_STATS rb_yjit_collect_binding_set(); #endif RB_OBJ_WRITE(env, ptr, val); return val; }
local_variables → Array 点击切换源代码
以符号形式返回绑定中的局部变量名称。
def foo a = 1 2.times do |n| binding.local_variables #=> [:a, :n] end end
此方法是以下代码的简短版本
binding.eval("local_variables")
static VALUE bind_local_variables(VALUE bindval) { const rb_binding_t *bind; const rb_env_t *env; GetBindingPtr(bindval, bind); env = VM_ENV_ENVVAL_PTR(vm_block_ep(&bind->block)); return rb_vm_env_local_variables(env); }
receiver → object 点击切换源代码
返回绑定对象的绑定接收者。
static VALUE bind_receiver(VALUE bindval) { const rb_binding_t *bind; GetBindingPtr(bindval, bind); return vm_block_self(&bind->block); }
source_location → [String, Integer] 点击切换源代码
返回绑定对象的 Ruby 源文件名和行号。
static VALUE bind_location(VALUE bindval) { VALUE loc[2]; const rb_binding_t *bind; GetBindingPtr(bindval, bind); loc[0] = pathobj_path(bind->pathobj); loc[1] = INT2FIX(bind->first_lineno); return rb_ary_new4(2, loc); }