我正在阅读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),而在第二个例子中必须使用它。
我给了它一些想法,但无法理解。
谢谢!
答案 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
内,或某些用户创建了后代类。