Ruby 为什么选择Module.methods()并响应?在irb中的工作方式与在脚本中的工作方式不同?

Ruby 为什么选择Module.methods()并响应?在irb中的工作方式与在脚本中的工作方式不同?,ruby,reflection,metaprogramming,irb,Ruby,Reflection,Metaprogramming,Irb,我尝试在Ruby中使用反射方法,并遇到了一个我觉得非常令人惊讶的行为 以下示例在IRB和ruby脚本中的工作方式似乎有所不同: 例1: def myfun; end p respond_to?(:myfun) 在IRb中,这表示“正确”, 在脚本中:“false” 例2: ml = methods def myfun; end p methods - ml 在IRb中,这表示[:myfun]。 脚本:[] 我在1.8、1.9 MRI、JRuby 1.5.6等中发现了这一点,所以我认为这是正常

我尝试在Ruby中使用反射方法,并遇到了一个我觉得非常令人惊讶的行为

以下示例在IRB和ruby脚本中的工作方式似乎有所不同:

例1:

def myfun; end
p respond_to?(:myfun)
在IRb中,这表示“正确”, 在脚本中:“false”

例2:

ml = methods
def myfun; end
p methods - ml
在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
如果您显式地在self上调用它,您将得到一个错误:

self.myfun
# NoMethodError: private method ‘myfun’ called for main:Object
另一方面,在IRB中,您的方法被定义为public。引擎盖下看起来像这样:

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
IRB可以很容易地在顶层进行评估,但它使用该方法创建了一个单独的环境,以便不共享局部变量:

require "irb"
foo = :ok
IRB.start
#>> foo
# NameError: undefined local variable or method `foo' for main:Object

我认为方法的公开只是一个巧合,因为它的实现并不重要。不管怎样,这些方法都是暂时的。

很高兴知道-令人惊讶的是,在多年的Ruby曝光之后,我没有遇到过这种情况。。是的,我感兴趣的是为什么IRB会把它们公之于众——它试图变得更友好——是吗?:)我能理解为什么它们通常是私有的——以避免像“def;end;class A;end;A.new.f”之类的混淆?@Semyon你能解释一下为什么
irb
方法是公共的吗?为什么在
irb
myfun
self.myfun
中引用了相同的方法?请记录:使用Pry尝试过。。这与独立脚本是一致的:顶级方法是私有的(所以response_to?返回false)。@codeit-只是为了回答后一个问题“为什么myfun和self.myfun引用相同的方法”-AFAIK在Ruby中调用任何方法时都是这样:如果省略self,它仍然会被忽略。(OTOH:def self.myfun..将完全不同:一个类方法)我相信这只是一个巧合(由于实现),IRB并不打算这样做。它只在独立程序中起作用。(“为什么”是另一个问题:-)