2016-03-08 35 views
0

爲什麼在class_eval之前創建的a在代碼中有權訪問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 如何在幕後工作?

回答

6

ruby​​中的類已打開。由於Hello是用一個新的方法給出的,因此在所有實例上的方法調度都被這個更新了。如果你想擴展a只,呼籲class_evala的eigenclass:

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> 
+2

你不需要'class_eval {'...'}'。 – sawa

+0

@sawa我是複製粘貼的奴隸。 Thx,已更新。 – mudasobwa

0

爲什麼a創建之前class_eval代碼訪問world

它沒有。方法存儲在模塊中,而不是實例。 (好吧,模塊是Module實例,但是這無關緊要這裏)。所有a知道的是,它的Hello的實例,即其class指針指向Hello(再次,從技術上講,這不是事實,其class指針指向它的單例類和它的單例類的superclass指針指向Hello,但在這裏也是不相關的)。當a獲得world消息發送world消息它檢查它的類,Hello,爲一個world方法,並且確實有一個,因爲它是在消息發送之前添加的,因此它執行它。

class_eval 如何在幕後工作?

這與class_eval沒有任何關係,它可以在沒有元編程的情況下以完全相同的方式工作。 class_eval這裏是一條紅鯡魚:

class Hello; end 

a = Hello.new 

class Hello; def world; puts "Hi" end end 

b = Hello.new 

a.world # "Hi" 
b.world # "Hi" 
相關問題