ing*_*ger 5 ruby reflection metaprogramming irb
我正在尝试在Ruby中使用反射方法,并遇到一种我觉得很惊讶的行为.
以下示例似乎在IRB中以及在调用ruby脚本时的工作方式不同:
例1:
def myfun; end
p respond_to?(:myfun)
Run Code Online (Sandbox Code Playgroud)
在IRb中,这表示'true',在脚本中:'false'.
例2:
ml = methods
def myfun; end
p methods - ml
Run Code Online (Sandbox Code Playgroud)
在IRb中,这表示[:myfun].在脚本中:[].
我发现这是1.8,1.9 MRI,JRuby 1.5.6等 - 所以我认为这是正常的.
为什么有区别?
我很确定'respond_to?' 是一种方法来查看方法是否可用 - 为什么在上述情况下不起作用?
此函数 - "main"对象上的方法 - 在ruby脚本中定义为private.您可以轻松检查:
ml = private_methods
def myfun; end
p private_methods - ml #=> [:myfun]
p respond_to?(:myfun, true) #=> true
Run Code Online (Sandbox Code Playgroud)
如果你在self上明确地调用它,你会收到一个错误:
self.myfun
# NoMethodError: private method ‘myfun’ called for main:Object
Run Code Online (Sandbox Code Playgroud)
另一方面,在IRB中,您的方法被定义为公共方法.在引擎盖下它看起来像这样:
class Object
def irb_binding
# this is where your entered code is evaluated
def myfun; :ok; end # you can define methods in other methods
self.myfun # and they are public by default
end
end
p irb_binding # :ok
Run Code Online (Sandbox Code Playgroud)
IRB可以轻松地在顶层进行评估,但是它会使用该方法创建一个单独的环境,以便不共享局部变量:
require "irb"
foo = :ok
IRB.start
#>> foo
# NameError: undefined local variable or method `foo' for main:Object
Run Code Online (Sandbox Code Playgroud)
我认为公开的方法只是一个巧合,因为它的实施并没有多大关系.这些方法无论如何都是暂时的.