Ruby ruby send 的一些疑惑

Daniel_Xu · 2013年03月06日 · 最后由 moofox 回复于 2013年04月11日 · 4041 次阅读
def define_methods
  shared = 1

  Kernel.send :define_method, :counter do
    puts shared
  end

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

define_methods
counter
inc(3, 4)
counter
  1. 这里是 send 的动态派发的特性,我查了 send 是 Object#send,即是 Object 的实例方法,而这为什么可以像类方法一样调用呢?

  2. 假设问题 1 已经解决,是什么保证了 定义的方法在顶级作用域中?我个人认为和 Kernel 有关,所以请 ruby 高手指点下

Q1:ruby 类也是对象。

Q2:顶级作用域消息都发给一个特殊的对象。

说的不对,请指教。

确实和 Kernel 有关,是一个必须的 mixin。

@zgm 我知道 ruby 类也是对象,我的疑问在这里:

send 是实例方法,理应是 实例对象.send , 可 Kernel 明显不是实例对象,虽然 Module 也是对象,请细说下这里

@Daniel_Xu 为什么你认为 Kernel 不是实例对象呢?Kernel 是 Module 类的一个实例对象啊!

puts Kernel.class.inspect

#4 楼 @neverlandxy_naix 好了,我明白了

总结下:Module # define_method(), 而 Kernel 是 Module 的实例对象,所以 Kernel.send :define_method 可以理解了

Q2 main 是 Object 的一个实例对象,而 Oject 的上一层是 Kernel, 所以 Kernel.send :define_method 必然在顶级作用域

irb(main):004:0> Object.superclass => BasicObjec #5 楼 @Daniel_Xu

#7 楼 @chenge sorry kernel 是 一个匿名类,用 ancestors() 可以找到

@Daniel_Xu 我学元编程的时候用 word 画的一张图,希望对你有帮助 Ruby 类体系

Kernel.send :define_method ...

你是向 Kernel 发送的消息,当然就定义在了顶级作用域

Object.ancestors
=> [Object, Kernel, BasicObject]

还有个问题是那个 shared 变量是个局部变量,为什么会一直有效呢?这就是所谓的闭包么?

#12 楼 @chenge 在你的例子中是闭包的一个例子。

@chenge 可以这么认为,其实就是用一些办法替代了 作用域门 ,闭包只是其中的一种办法。

block 本身就是闭包

#12 楼 @chenge 是闭包,do...end 的代码块起到了闭包的作用

#12 楼 @chenge 这就是传说中的扁平作用域

为什么在类中使用:define_method 定义出来的是实例方法?

需要 登录 后方可回复, 如果你还没有账号请 注册新账号