Ruby define_method问题

时间:2010-07-30 08:58:52

标签: ruby

我正在阅读Ruby中的元编程。

以下是本书中的两个代码片段:

my_var = "Success"

MyClass = Class.new do 
  puts "#{my_var} in the class definition!"
  define_method :my_method do
    puts "#{my_var} in the method!"
  end
end

MyClass.new.my_method

⇒ Success in the class definition!
  Success in the method!

def define_methods
  shared = 0

  Kernel.send :define_method, :counter do
    shared
  end

  Kernel.send :define_method, :inc do |x|
    shared += x
  end
end

define_methods

counter # => 0 
inc(4) 
counter # => 4

我想知道为什么在第一个例子中定义方法时不必使用动态调度(使用Kernel.send),而在第二个例子中必须使用它。

我给了它一些想法,但无法理解。

谢谢!

2 个答案:

答案 0 :(得分:5)

Module#define_method是私有的。私有方法只能在没有接收器的情况下调用。因此,在第二个示例中,您需要使用反射(即send)来规避访问限制。

请注意,第一个示例仍然使用动态分派。实际上,在Ruby中,所有(变量访问和一些内置运算符除外)都使用动态调度。

答案 1 :(得分:1)

与本书所说的相反,它在没有Kernel.send的情况下工作,您只需要一个self的类包含Kernel的上下文 - 这几乎总是如此。

例如,如果你在主范围内这样做,它就在那里:

irb(main):024:0> self.class.ancestors
=> [Object, Kernel, BasicObject]

所以,使用

  define_method :counter do
    shared
  end

工作正常。

如果在当前上下文中未包含Kernel,则只需要该技巧,例如如果您在普通BasicObject内,或某些用户创建了后代类。