在方法定义之前创建的实例

时间:2016-03-08 13:19:39

标签: ruby

为什么代码a之前创建的class_eval可以访问world

class Hello; end

a = Hello.new

Hello.class_eval {def world; puts "Hi" end}

b = Hello.new

a.world #=> "Hi"
b.world #=> "Hi"

class_eval如何在幕后工作?

2 个答案:

答案 0 :(得分:6)

ruby​​中的类是开放的。当使用新方法给出Hello时,所有实例上的方法调度都已更新。如果您只想展开a,请在class_eval的本征类上致电a

class Hello; end

a = Hello.new

class << a; def world; puts "Hi" end end
# or, the equivalent: 
# a.singleton_class.class_eval { def world; puts "Hi" end }

b = Hello.new

a.world #⇒ "Hi"
b.world #⇒ NoMethodError: undefined method `world' for #<Hello>

答案 1 :(得分:0)

  

为什么代码a之前创建的class_eval可以访问world

它没有。方法存储在模块中,而不是实例中。 (好吧,模块是Module的实例,但这里不相关。)所有a都知道它是Hello的一个实例,即它的{{} 1}}指针指向class(再次,从技术上讲,它不是真的,它的Hello指针指向它的单例类及其单例类的class指针点到superclass,但这也与此无关)。当Hello发送a消息时,它会检查其类world,以查找Hello方法,果然,有一个因为它是在消息之前添加的发送,所以它执行它。

  

world如何在幕后工作?

这与class_eval无关,如果没有元编程,它的工作方式完全相同。 class_eval在这里是一个红鲱鱼:

class_eval